From e14f6f5763098aee0c5cfde2637d45f1eef364a1 Mon Sep 17 00:00:00 2001 From: Ovahlord <18347559+ovahlord@users.noreply.github.com> Date: Wed, 14 Oct 2026 10:38:34 +0200 Subject: [PATCH 1/5] Read Storage fields as strongly typed values where possible to reduce boxing --- DBCD.IO/Common/IPrimitiveSetter.cs | 36 ++++++++++++++++ DBCD.IO/Extensions.cs | 23 +++++++---- DBCD.IO/FieldCache.cs | 3 +- DBCD.IO/Readers/HTFXReader.cs | 34 +++++++++++++-- DBCD.IO/Readers/WDB2Reader.cs | 58 ++++++++++++++------------ DBCD.IO/Readers/WDB3Reader.cs | 60 ++++++++++++++++----------- DBCD.IO/Readers/WDB4Reader.cs | 47 +++++++++++++++------ DBCD.IO/Readers/WDB5Reader.cs | 62 ++++++++++++++++------------ DBCD.IO/Readers/WDB6Reader.cs | 47 +++++++++++++++------ DBCD.IO/Readers/WDBCReader.cs | 57 ++++++++++++++------------ DBCD.IO/Readers/WDC1Reader.cs | 60 ++++++++++++++++----------- DBCD.IO/Readers/WDC2Reader.cs | 62 ++++++++++++++++------------ DBCD.IO/Readers/WDC3Reader.cs | 66 +++++++++++++++++------------- DBCD.IO/Readers/WDC4Reader.cs | 64 ++++++++++++++++------------- DBCD.IO/Readers/WDC5Reader.cs | 47 +++++++++++++++------ 15 files changed, 466 insertions(+), 260 deletions(-) create mode 100644 DBCD.IO/Common/IPrimitiveSetter.cs diff --git a/DBCD.IO/Common/IPrimitiveSetter.cs b/DBCD.IO/Common/IPrimitiveSetter.cs new file mode 100644 index 0000000..df488ae --- /dev/null +++ b/DBCD.IO/Common/IPrimitiveSetter.cs @@ -0,0 +1,36 @@ +using System; +using System.Runtime.CompilerServices; + +namespace DBCD.IO.Common; + +public interface IPrimitiveSetter +{ + // Value type setter for value type objects + void SetValue(T refObject, TValue value) where TValue : struct; + + // Fallback setter for value type assignments + void SetObject(T target, object value); +} + +public class PrimitiveSetter : IPrimitiveSetter +{ + private readonly Action _setter; + + public PrimitiveSetter(Action setter) + { + _setter = setter; + } + + public void SetValue(T target, TValue value) where TValue : struct + { + if (typeof(TValue) == typeof(TField)) + _setter(target, Unsafe.As(ref value)); + else + _setter(target, (TField)Convert.ChangeType(value, typeof(TField))); + } + + public void SetObject(T target, object value) + { + _setter(target, (TField)value); + } +} \ No newline at end of file diff --git a/DBCD.IO/Extensions.cs b/DBCD.IO/Extensions.cs index b7661ed..629eda3 100644 --- a/DBCD.IO/Extensions.cs +++ b/DBCD.IO/Extensions.cs @@ -9,20 +9,29 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +using DBCD.IO.Common; namespace DBCD.IO { static class Extensions { - public static Action GetSetter(this FieldInfo fieldInfo) + public static IPrimitiveSetter GetSetter(this FieldInfo fieldInfo) { - var paramExpression = Expression.Parameter(typeof(T)); - var propertyExpression = Expression.Field(paramExpression, fieldInfo); - var valueExpression = Expression.Parameter(typeof(object)); - var convertExpression = Expression.Convert(valueExpression, fieldInfo.FieldType); - var assignExpression = Expression.Assign(propertyExpression, convertExpression); + Type fieldType = fieldInfo.FieldType; + + var target = Expression.Parameter(typeof(T), "target"); + var value = Expression.Parameter(fieldType, "value"); + var field = Expression.Field(target, fieldInfo); + var assign = Expression.Assign(field, value); + + // Compile to exact Action + var actionType = typeof(Action<,>).MakeGenericType(typeof(T), fieldType); + var lambda = Expression.Lambda(actionType, assign, target, value); + object compiledDelegate = lambda.Compile(); - return Expression.Lambda>(assignExpression, paramExpression, valueExpression).Compile(); + var closedSetterType = typeof(PrimitiveSetter<,>).MakeGenericType(typeof(T), fieldType); + var ctor = closedSetterType.GetConstructor(new[] { actionType }); + return (IPrimitiveSetter)ctor.Invoke(new[] { compiledDelegate }); } public static Func GetGetter(this FieldInfo fieldInfo) diff --git a/DBCD.IO/FieldCache.cs b/DBCD.IO/FieldCache.cs index f8a08dd..e48d880 100644 --- a/DBCD.IO/FieldCache.cs +++ b/DBCD.IO/FieldCache.cs @@ -1,6 +1,7 @@ using DBCD.IO.Attributes; using System; using System.Reflection; +using DBCD.IO.Common; namespace DBCD.IO { @@ -9,7 +10,7 @@ class FieldCache public readonly FieldInfo Field; public readonly bool IsArray = false; public readonly bool IsLocalisedString = false; - public readonly Action Setter; + public readonly IPrimitiveSetter Setter; public readonly Func Getter; public readonly LocaleAttribute LocaleInfo; diff --git a/DBCD.IO/Readers/HTFXReader.cs b/DBCD.IO/Readers/HTFXReader.cs index de7f3de..1ab3014 100644 --- a/DBCD.IO/Readers/HTFXReader.cs +++ b/DBCD.IO/Readers/HTFXReader.cs @@ -68,7 +68,7 @@ public void GetFields(FieldCache[] fields, T entry) FieldCache info = fields[i]; if (info.IndexMapField) { - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } @@ -92,11 +92,11 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IsNonInlineRelation) { var casted = Convert.ChangeType(value, info.FieldType); - info.Setter(entry, casted); + info.Setter.SetObject(entry, casted); } else { - info.Setter(entry, value); + info.Setter.SetObject(entry, value); } } } @@ -115,7 +115,33 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(string)) + info.Setter.SetObject(record, data.ReadCString()); + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + #region Interface Methods public IDBRow Clone() diff --git a/DBCD.IO/Readers/WDB2Reader.cs b/DBCD.IO/Readers/WDB2Reader.cs index ce6e446..97ec080 100644 --- a/DBCD.IO/Readers/WDB2Reader.cs +++ b/DBCD.IO/Readers/WDB2Reader.cs @@ -24,20 +24,7 @@ public WDB2Row(BaseReader reader, BitReader data, int recordIndex) Id = m_recordIndex = recordIndex + 1; } - - private static Dictionary, BaseReader, object>> simpleReaders = new Dictionary, BaseReader, object>> - { - [typeof(long)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(float)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(int)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(uint)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(short)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(ushort)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(sbyte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(byte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(string)] = (data, stringTable, header) => stringTable[GetFieldValue(data)], - }; - + private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -60,34 +47,26 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IndexMapField) { Id = GetFieldValue(Data); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; - if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Data, m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else if (info.IsLocalisedString) { Data.Position += 32 * info.LocaleInfo.Locale; - value = simpleReaders[typeof(string)](Data, m_reader.StringTable, m_reader); + info.Setter.SetObject(entry, m_reader.StringTable[GetFieldValue(Data)]); Data.Position += 32 * (info.LocaleInfo.LocaleCount - info.LocaleInfo.Locale); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } + ReadStronglyTyped(entry, info, Data, m_reader.StringTable); - info.Setter(entry, value); } } @@ -105,6 +84,33 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(string)) + info.Setter.SetObject(record, stringTable[GetFieldValue(data)]); + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDB3Reader.cs b/DBCD.IO/Readers/WDB3Reader.cs index 2184096..376d7c3 100644 --- a/DBCD.IO/Readers/WDB3Reader.cs +++ b/DBCD.IO/Readers/WDB3Reader.cs @@ -30,19 +30,6 @@ public WDB3Row(BaseReader reader, BitReader data, int id, int recordIndex) m_dataPosition = Data.Position; } - private static Dictionary, BaseReader, object>> simpleReaders = new Dictionary, BaseReader, object>> - { - [typeof(long)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(float)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(int)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(uint)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(short)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(ushort)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(sbyte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(byte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(string)] = (data, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : stringTable[GetFieldValue(data)], - }; - private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -74,36 +61,28 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; // 0x2 SecondaryKey if (fieldIndex >= m_reader.FieldsCount) { - info.Setter(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Data, m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Data, m_reader.StringTable, m_reader); } } @@ -121,6 +100,37 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDB4Reader.cs b/DBCD.IO/Readers/WDB4Reader.cs index 361c91d..f25a951 100644 --- a/DBCD.IO/Readers/WDB4Reader.cs +++ b/DBCD.IO/Readers/WDB4Reader.cs @@ -74,36 +74,28 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; // 0x2 SecondaryKey if (fieldIndex >= m_reader.FieldsCount) { - info.Setter(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Data, m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Data, m_reader.StringTable, m_reader); } } @@ -120,6 +112,37 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } + + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDB5Reader.cs b/DBCD.IO/Readers/WDB5Reader.cs index ed2e65d..d60578d 100644 --- a/DBCD.IO/Readers/WDB5Reader.cs +++ b/DBCD.IO/Readers/WDB5Reader.cs @@ -32,19 +32,6 @@ public WDB5Row(BaseReader reader, BitReader data, int id, int recordIndex) m_fieldMeta = reader.Meta; } - private static Dictionary, BaseReader, object>> simpleReaders = new Dictionary, BaseReader, object>> - { - [typeof(long)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(float)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(int)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(uint)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(short)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(ushort)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(sbyte)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(byte)] = (data, fieldMeta, stringTable, header) => GetFieldValue(data, fieldMeta), - [typeof(string)] = (data, fieldMeta, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : stringTable[GetFieldValue(data, fieldMeta)], - }; - private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, fieldMeta, stringTable, cardinality) => GetFieldValueArray(data, fieldMeta, cardinality), @@ -81,17 +68,16 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data, m_fieldMeta[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; // 0x2 SecondaryKey if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); continue; } @@ -101,19 +87,12 @@ public void GetFields(FieldCache[] fields, T entry) SetCardinality(info, fieldIndex); if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_fieldMeta[fieldIndex], m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Data, m_fieldMeta[fieldIndex], m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_fieldMeta[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Data, m_fieldMeta[fieldIndex], m_reader.StringTable, m_reader); } } @@ -152,7 +131,38 @@ private static T[] GetFieldValueArray(BitReader r, FieldMetaData fieldMeta, i return array; } - + + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, FieldMetaData fieldMeta , Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data, fieldMeta)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDB6Reader.cs b/DBCD.IO/Readers/WDB6Reader.cs index 0d4dea4..66c010c 100644 --- a/DBCD.IO/Readers/WDB6Reader.cs +++ b/DBCD.IO/Readers/WDB6Reader.cs @@ -80,17 +80,16 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], CommonData?[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; // 0x2 SecondaryKey if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_reader.ForeignKeyData[Id - m_reader.MinIndex], info.FieldType)); continue; } @@ -100,19 +99,12 @@ public void GetFields(FieldCache[] fields, T entry) SetCardinality(info, fieldIndex); if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, m_reader); } } @@ -160,6 +152,37 @@ private static T[] GetFieldValueArray(int Id, BitReader r, FieldMetaData fiel return array; } + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, FieldMetaData fieldMeta, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, commonData)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDBCReader.cs b/DBCD.IO/Readers/WDBCReader.cs index 0f3d6e9..04561e3 100644 --- a/DBCD.IO/Readers/WDBCReader.cs +++ b/DBCD.IO/Readers/WDBCReader.cs @@ -25,19 +25,6 @@ public WDBCRow(BaseReader reader, BitReader data, int recordIndex) Id = m_recordIndex = recordIndex + 1; } - private static Dictionary, BaseReader, object>> simpleReaders = new Dictionary, BaseReader, object>> - { - [typeof(long)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(float)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(int)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(uint)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(short)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(ushort)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(sbyte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(byte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(string)] = (data, stringTable, header) => stringTable[GetFieldValue(data)], - }; - private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -61,34 +48,25 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IndexMapField) { Id = GetFieldValue(Data); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; - if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, info.Cardinality); + info.Setter.SetObject(entry, reader(Data, m_reader.StringTable, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else if (info.IsLocalisedString) { Data.Position += 32 * info.LocaleInfo.Locale; - value = simpleReaders[typeof(string)](Data, m_reader.StringTable, m_reader); + info.Setter.SetObject(entry, m_reader.StringTable[GetFieldValue(Data)]); Data.Position += 32 * (info.LocaleInfo.LocaleCount - info.LocaleInfo.Locale); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Data, m_reader.StringTable); } } @@ -105,6 +83,33 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } + + private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(data)); + else if (info.FieldType == typeof(string)) + info.Setter.SetObject(record, stringTable[GetFieldValue(data)]); + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDC1Reader.cs b/DBCD.IO/Readers/WDC1Reader.cs index 673f7ab..039cb3a 100644 --- a/DBCD.IO/Readers/WDC1Reader.cs +++ b/DBCD.IO/Readers/WDC1Reader.cs @@ -42,19 +42,6 @@ public WDC1Row(BaseReader reader, BitReader data, int id, int refID, int recordI Id = id; } - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> - { - [typeof(long)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(float)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(uint)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(ushort)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(sbyte)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(byte)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(string)] = (id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)], - }; - private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -86,35 +73,27 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_refID, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_refID, info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable); + info.Setter.SetObject(entry, reader(Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); } } @@ -196,6 +175,37 @@ private static T[] GetFieldValueArray(BitReader r, FieldMetaData fieldMeta, C throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC2Reader.cs b/DBCD.IO/Readers/WDC2Reader.cs index fefd853..b5bdc8a 100644 --- a/DBCD.IO/Readers/WDC2Reader.cs +++ b/DBCD.IO/Readers/WDC2Reader.cs @@ -44,21 +44,6 @@ public WDC2Row(BaseReader reader, BitReader data, int recordsOffset, int id, int Id = id; } - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> - { - [typeof(ulong)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(long)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(float)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(uint)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(ushort)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(sbyte)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(byte)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(string)] = (id, data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : - stringTable[(recordsOffset + data.Offset + (data.Position >> 3)) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)], - }; - private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -100,16 +85,15 @@ public void GetFields(FieldCache[] fields, T entry) Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); } - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_refID, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_refID, info.FieldType)); continue; } @@ -122,19 +106,12 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable); + info.Setter.SetObject(entry, (Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); } } @@ -237,6 +214,37 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[(recordOffset + data.Offset + (data.Position >> 3)) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC3Reader.cs b/DBCD.IO/Readers/WDC3Reader.cs index e09d1ab..4edcd53 100644 --- a/DBCD.IO/Readers/WDC3Reader.cs +++ b/DBCD.IO/Readers/WDC3Reader.cs @@ -44,21 +44,6 @@ public WDC3Row(BaseReader reader, BitReader data, int id, int refID, int recordI Id = id; } - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> - { - [typeof(ulong)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(long)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(float)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(uint)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(ushort)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(sbyte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(byte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(string)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : - getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData), - }; - private static string getStringTableRecord(Dictionary stringTable, int recordOffset, int id, BitReader data, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData) { var index = recordOffset + (data.Position >> 3) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData); @@ -101,35 +86,27 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - - object value = null; + int fieldIndex = i - indexFieldOffSet; if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_refID, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_refID, info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable); + info.Setter.SetObject(entry, reader(Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); } } @@ -236,7 +213,38 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - + + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC4Reader.cs b/DBCD.IO/Readers/WDC4Reader.cs index 3fa0a4f..84f7b3e 100644 --- a/DBCD.IO/Readers/WDC4Reader.cs +++ b/DBCD.IO/Readers/WDC4Reader.cs @@ -44,21 +44,6 @@ public WDC4Row(BaseReader reader, BitReader data, int id, int refID, int recordI Id = id; } - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> - { - [typeof(ulong)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(long)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(float)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(uint)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(ushort)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(sbyte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(byte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(string)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : - getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData), - }; - private static string getStringTableRecord(Dictionary stringTable, int recordOffset, int id, BitReader data, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData) { var index = recordOffset + (data.Position >> 3) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData); @@ -101,35 +86,27 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_refID, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_refID, info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable); + info.Setter.SetObject(entry, reader(Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); } } @@ -236,7 +213,38 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - + + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC5Reader.cs b/DBCD.IO/Readers/WDC5Reader.cs index 5039071..c1d29cc 100644 --- a/DBCD.IO/Readers/WDC5Reader.cs +++ b/DBCD.IO/Readers/WDC5Reader.cs @@ -102,35 +102,27 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, m_data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter(entry, Convert.ChangeType(Id, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - object value = null; int fieldIndex = i - indexFieldOffSet; if (fieldIndex >= m_reader.Meta.Length) { - info.Setter(entry, Convert.ChangeType(m_refID, info.FieldType)); + info.Setter.SetObject(entry, Convert.ChangeType(m_refID, info.FieldType)); continue; } if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable); + info.Setter.SetObject(entry, reader(m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else - { - if (simpleReaders.TryGetValue(info.FieldType, out var reader)) - value = reader(Id, m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - - info.Setter(entry, value); + ReadStronglyTyped(entry, info, Id, m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); } } @@ -238,6 +230,37 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } + private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) + { + // This is not very pretty, but it is required to avoid boxing the read values + if (info.FieldType == typeof(ulong)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(long)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(float)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(uint)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(int)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(ushort)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(short)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(byte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(sbyte)) + info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); + else if (info.FieldType == typeof(string)) + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + else + throw new Exception("Unhandled field type: " + typeof(T).Name); + } + public IDBRow Clone() { return (IDBRow)MemberwiseClone(); From 07a2170d7c1b21c67c6a15d04874397cbd050756 Mon Sep 17 00:00:00 2001 From: Ovahlord <18347559+ovahlord@users.noreply.github.com> Date: Wed, 14 Oct 2026 11:31:04 +0200 Subject: [PATCH 2/5] fixed a typo --- DBCD.IO/Readers/WDC2Reader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DBCD.IO/Readers/WDC2Reader.cs b/DBCD.IO/Readers/WDC2Reader.cs index b5bdc8a..83971fe 100644 --- a/DBCD.IO/Readers/WDC2Reader.cs +++ b/DBCD.IO/Readers/WDC2Reader.cs @@ -106,7 +106,7 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IsArray) { if (arrayReaders.TryGetValue(info.FieldType, out var reader)) - info.Setter.SetObject(entry, (Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); + info.Setter.SetObject(entry, reader(Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } From fecfa6f6fa34d0c84645458b8777a810f4bcd57e Mon Sep 17 00:00:00 2001 From: Ovahlord <18347559+ovahlord@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:24:08 +0200 Subject: [PATCH 3/5] Converted the large if-else branch into an action dictionary --- DBCD.IO/Extensions.cs | 2 +- DBCD.IO/Readers/HTFXReader.cs | 73 +++++++++++------------------------ DBCD.IO/Readers/WDB2Reader.cs | 49 ++++++++++------------- DBCD.IO/Readers/WDB3Reader.cs | 58 +++++++++++++--------------- DBCD.IO/Readers/WDB4Reader.cs | 69 ++++++++++++--------------------- DBCD.IO/Readers/WDB5Reader.cs | 58 +++++++++++++--------------- DBCD.IO/Readers/WDB6Reader.cs | 39 ++++++++++++------- DBCD.IO/Readers/WDBCReader.cs | 53 ++++++++++++------------- DBCD.IO/Readers/WDC1Reader.cs | 58 +++++++++++++--------------- DBCD.IO/Readers/WDC2Reader.cs | 62 ++++++++++++++--------------- DBCD.IO/Readers/WDC3Reader.cs | 58 +++++++++++++--------------- DBCD.IO/Readers/WDC4Reader.cs | 58 +++++++++++++--------------- DBCD.IO/Readers/WDC5Reader.cs | 58 +++++++++++++--------------- 13 files changed, 303 insertions(+), 392 deletions(-) diff --git a/DBCD.IO/Extensions.cs b/DBCD.IO/Extensions.cs index 629eda3..026f916 100644 --- a/DBCD.IO/Extensions.cs +++ b/DBCD.IO/Extensions.cs @@ -31,7 +31,7 @@ public static IPrimitiveSetter GetSetter(this FieldInfo fieldInfo) var closedSetterType = typeof(PrimitiveSetter<,>).MakeGenericType(typeof(T), fieldType); var ctor = closedSetterType.GetConstructor(new[] { actionType }); - return (IPrimitiveSetter)ctor.Invoke(new[] { compiledDelegate }); + return (IPrimitiveSetter)ctor?.Invoke(new[] { compiledDelegate }); } public static Func GetGetter(this FieldInfo fieldInfo) diff --git a/DBCD.IO/Readers/HTFXReader.cs b/DBCD.IO/Readers/HTFXReader.cs index 1ab3014..1e59a29 100644 --- a/DBCD.IO/Readers/HTFXReader.cs +++ b/DBCD.IO/Readers/HTFXReader.cs @@ -31,19 +31,22 @@ public HTFXRow(BitReader data, IHotfixEntry hotfixEntry) Id = hotfixEntry.RecordId; } - private static Dictionary> simpleReaders = new Dictionary> + private static class SingleReaderCache { - [typeof(ulong)] = (data) => GetFieldValue(data), - [typeof(long)] = (data) => GetFieldValue(data), - [typeof(float)] = (data) => GetFieldValue(data), - [typeof(int)] = (data) => GetFieldValue(data), - [typeof(uint)] = (data) => GetFieldValue(data), - [typeof(short)] = (data) => GetFieldValue(data), - [typeof(ushort)] = (data) => GetFieldValue(data), - [typeof(sbyte)] = (data) => GetFieldValue(data), - [typeof(byte)] = (data) => GetFieldValue(data), - [typeof(string)] = (data) => data.ReadCString(), - }; + public static readonly Dictionary, BitReader>> Readers = new() + { + { typeof(long), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(ulong), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(float), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(uint), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(int), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(ushort), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(short), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(byte), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(sbyte), (record, info, data) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(string), (record, info, data) => info.Setter.SetObject(record, data.ReadCString()) } + }; + } private static Dictionary> arrayReaders = new Dictionary> { @@ -71,33 +74,30 @@ public void GetFields(FieldCache[] fields, T entry) info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } - - object value = null; - + if (info.IsArray) { if (arrayReaders.TryGetValue(info.MetaDataFieldType, out var reader)) - value = reader(m_data, info.Cardinality); + info.Setter.SetObject(entry, reader(m_data, info.Cardinality)); else throw new Exception("Unhandled array type: " + typeof(T).Name); } else { - if (simpleReaders.TryGetValue(info.MetaDataFieldType, out var reader)) - value = reader(m_data); + if (SingleReaderCache.Readers.TryGetValue(info.MetaDataFieldType, out var reader)) + reader(entry, info, m_data); else throw new Exception("Unhandled field type: " + typeof(T).Name); } + /* + The strongly typed Setter does take care of converting mismatching types already if (info.IsNonInlineRelation) { - var casted = Convert.ChangeType(value, info.FieldType); + var casted = Convert.ChangeType(info.Getter(entry), info.FieldType); info.Setter.SetObject(entry, casted); } - else - { - info.Setter.SetObject(entry, value); - } + */ } } @@ -114,33 +114,6 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(string)) - info.Setter.SetObject(record, data.ReadCString()); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } #region Interface Methods diff --git a/DBCD.IO/Readers/WDB2Reader.cs b/DBCD.IO/Readers/WDB2Reader.cs index 97ec080..0f58ab8 100644 --- a/DBCD.IO/Readers/WDB2Reader.cs +++ b/DBCD.IO/Readers/WDB2Reader.cs @@ -24,6 +24,23 @@ public WDB2Row(BaseReader reader, BitReader data, int recordIndex) Id = m_recordIndex = recordIndex + 1; } + + private static class SingleReaderCache + { + public static readonly Dictionary, BitReader, Dictionary>> Readers = new() + { + { typeof(ulong), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(long), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(float), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(uint), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(int), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(ushort), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(short), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(byte), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(sbyte), (record, info, data, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(string), (record, info, data, stringTable) => info.Setter.SetObject(record, stringTable[GetFieldValue(data)]) } + }; + } private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { @@ -64,9 +81,10 @@ public void GetFields(FieldCache[] fields, T entry) info.Setter.SetObject(entry, m_reader.StringTable[GetFieldValue(Data)]); Data.Position += 32 * (info.LocaleInfo.LocaleCount - info.LocaleInfo.Locale); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Data, m_reader.StringTable); else - ReadStronglyTyped(entry, info, Data, m_reader.StringTable); - + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -83,33 +101,6 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(string)) - info.Setter.SetObject(record, stringTable[GetFieldValue(data)]); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDB3Reader.cs b/DBCD.IO/Readers/WDB3Reader.cs index 376d7c3..8d7ad2f 100644 --- a/DBCD.IO/Readers/WDB3Reader.cs +++ b/DBCD.IO/Readers/WDB3Reader.cs @@ -30,6 +30,29 @@ public WDB3Row(BaseReader reader, BitReader data, int id, int recordIndex) m_dataPosition = Data.Position; } + private static class SingleReaderCache + { + public static readonly Dictionary, BitReader, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(long), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(float), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(uint), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(int), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(ushort), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(short), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(byte), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(sbyte), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(string), (record, info, data, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data)]; + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -81,8 +104,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Data, m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Data, m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -99,37 +124,6 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : stringTable[GetFieldValue(data)]; - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDB4Reader.cs b/DBCD.IO/Readers/WDB4Reader.cs index f25a951..f78038e 100644 --- a/DBCD.IO/Readers/WDB4Reader.cs +++ b/DBCD.IO/Readers/WDB4Reader.cs @@ -30,19 +30,29 @@ public WDB4Row(BaseReader reader, BitReader data, int id, int recordIndex) m_dataPosition = Data.Position; } - private static Dictionary, BaseReader, object>> simpleReaders = new Dictionary, BaseReader, object>> + private static class SingleReaderCache { - [typeof(long)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(float)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(int)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(uint)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(short)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(ushort)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(sbyte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(byte)] = (data, stringTable, header) => GetFieldValue(data), - [typeof(string)] = (data, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : stringTable[GetFieldValue(data)], - }; - + public static readonly Dictionary, BitReader, Dictionary, BaseReader>> Reader = new() + { + { typeof(ulong), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(long), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(float), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(uint), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(int), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(ushort), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(short), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(byte), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(sbyte), (record, info, data, _, _) => info.Setter.SetValue(record, GetFieldValue(data)) }, + { typeof(string), (record, info, data, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data)]; + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -94,8 +104,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Reader.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Data, m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Data, m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -112,37 +124,6 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : stringTable[GetFieldValue(data)]; - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDB5Reader.cs b/DBCD.IO/Readers/WDB5Reader.cs index d60578d..36e10b1 100644 --- a/DBCD.IO/Readers/WDB5Reader.cs +++ b/DBCD.IO/Readers/WDB5Reader.cs @@ -32,6 +32,29 @@ public WDB5Row(BaseReader reader, BitReader data, int id, int recordIndex) m_fieldMeta = reader.Meta; } + private static class SingleReaderCache + { + public static readonly Dictionary, BitReader, FieldMetaData , Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(long), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(float), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(uint), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(int), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(ushort), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(short), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(byte), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(sbyte), (record, info, data, fieldMeta, _, _) => info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)) }, + { typeof(string), (record, info, data, fieldMeta, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(data, fieldMeta)]; + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, fieldMeta, stringTable, cardinality) => GetFieldValueArray(data, fieldMeta, cardinality), @@ -91,8 +114,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Data, m_fieldMeta[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Data, m_fieldMeta[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -132,37 +157,6 @@ private static T[] GetFieldValueArray(BitReader r, FieldMetaData fieldMeta, i return array; } - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, FieldMetaData fieldMeta , Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data, fieldMeta)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : stringTable[GetFieldValue(data, fieldMeta)]; - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDB6Reader.cs b/DBCD.IO/Readers/WDB6Reader.cs index 66c010c..c629353 100644 --- a/DBCD.IO/Readers/WDB6Reader.cs +++ b/DBCD.IO/Readers/WDB6Reader.cs @@ -36,18 +36,29 @@ public WDB6Row(BaseReader reader, BitReader data, int id, int recordIndex) Id = id; } - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> + private static class SingleReaderCache { - [typeof(long)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(float)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(int)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(uint)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(short)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(ushort)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(sbyte)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(byte)] = (id, data, fieldMeta, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, commonData), - [typeof(string)] = (id, data, fieldMeta, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, commonData)], - }; + public static readonly Dictionary, int, BitReader, FieldMetaData, Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(long), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(float), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(uint), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(int), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(ushort), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(short), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(byte), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(sbyte), (record, info, id, data, fieldMeta, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, commonData)) }, + { typeof(string), (record, info, id, data, fieldMeta, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, commonData)]; + info.Setter.SetObject(record, stringValue); + } + + } + }; + } private static Dictionary, Dictionary, int, object>> arrayReaders = new Dictionary, Dictionary, int, object>> { @@ -79,7 +90,7 @@ public void GetFields(FieldCache[] fields, T entry) indexFieldOffSet++; else Id = GetFieldValue(0, Data, m_fieldMeta[i], CommonData?[i]); - + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } @@ -103,8 +114,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, Data, m_fieldMeta[fieldIndex], CommonData?[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } diff --git a/DBCD.IO/Readers/WDBCReader.cs b/DBCD.IO/Readers/WDBCReader.cs index 04561e3..9a36f94 100644 --- a/DBCD.IO/Readers/WDBCReader.cs +++ b/DBCD.IO/Readers/WDBCReader.cs @@ -25,6 +25,23 @@ public WDBCRow(BaseReader reader, BitReader data, int recordIndex) Id = m_recordIndex = recordIndex + 1; } + private static class SingleReaderCache + { + public static readonly Dictionary, BitReader, Dictionary>> Readers = new() + { + { typeof(long), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(ulong), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(float), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(uint), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(int), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(ushort), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(short), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(byte), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(sbyte), (entry, info, data, _) => info.Setter.SetValue(entry, GetFieldValue(data)) }, + { typeof(string), (entry, info, data, stringTable) => info.Setter.SetObject(entry, stringTable[GetFieldValue(data)]) } + }; + } + private static Dictionary, int, object>> arrayReaders = new Dictionary, int, object>> { [typeof(ulong[])] = (data, stringTable, cardinality) => GetFieldValueArray(data, cardinality), @@ -48,7 +65,10 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IndexMapField) { Id = GetFieldValue(Data); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } @@ -65,8 +85,10 @@ public void GetFields(FieldCache[] fields, T entry) info.Setter.SetObject(entry, m_reader.StringTable[GetFieldValue(Data)]); Data.Position += 32 * (info.LocaleInfo.LocaleCount - info.LocaleInfo.Locale); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader.Invoke(entry, info, Data, m_reader.StringTable); else - ReadStronglyTyped(entry, info, Data, m_reader.StringTable); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -83,33 +105,6 @@ private static T[] GetFieldValueArray(BitReader r, int cardinality) where T : return array; } - - private static void ReadStronglyTyped(T record, FieldCache info, BitReader data, Dictionary stringTable) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(data)); - else if (info.FieldType == typeof(string)) - info.Setter.SetObject(record, stringTable[GetFieldValue(data)]); - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDC1Reader.cs b/DBCD.IO/Readers/WDC1Reader.cs index 039cb3a..6d99123 100644 --- a/DBCD.IO/Readers/WDC1Reader.cs +++ b/DBCD.IO/Readers/WDC1Reader.cs @@ -42,6 +42,29 @@ public WDC1Row(BaseReader reader, BitReader data, int id, int refID, int recordI Id = id; } + private static class SingleReaderCache + { + public static readonly Dictionary, int, BitReader, FieldMetaData, ColumnMetaData, Value32[], Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(long), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(float), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(uint), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(int), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(ushort), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(short), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(byte), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(sbyte), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(string), (record, info, id, data, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -92,8 +115,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, Data, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -174,37 +199,6 @@ private static T[] GetFieldValueArray(BitReader r, FieldMetaData fieldMeta, C throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - - private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : stringTable[GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDC2Reader.cs b/DBCD.IO/Readers/WDC2Reader.cs index 83971fe..065f0ef 100644 --- a/DBCD.IO/Readers/WDC2Reader.cs +++ b/DBCD.IO/Readers/WDC2Reader.cs @@ -44,15 +44,38 @@ public WDC2Row(BaseReader reader, BitReader data, int recordsOffset, int id, int Id = id; } + private static class SingleReaderCache + { + public static readonly Dictionary, int, BitReader, int, FieldMetaData, ColumnMetaData, Value32[], Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(long), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(float), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(uint), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(int), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(ushort), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(short), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(byte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(sbyte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(string), (record, info, id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : stringTable[(recordOffset + data.Offset + (data.Position >> 3)) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(long[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(float[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(uint[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), + [typeof(int[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(ushort[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), + [typeof(short[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(byte[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(sbyte[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), [typeof(string[])] = (data, recordsOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueStringArray(data, fieldMeta, columnMeta, recordsOffset, stringTable), @@ -110,8 +133,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, Data, m_recordsOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -213,37 +238,6 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel } throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - - private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : stringTable[(recordOffset + data.Offset + (data.Position >> 3)) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)]; - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { diff --git a/DBCD.IO/Readers/WDC3Reader.cs b/DBCD.IO/Readers/WDC3Reader.cs index 4edcd53..ef7e7c6 100644 --- a/DBCD.IO/Readers/WDC3Reader.cs +++ b/DBCD.IO/Readers/WDC3Reader.cs @@ -55,6 +55,29 @@ private static string getStringTableRecord(Dictionary stringTable, return stringTable[index]; } + private static class SingleReaderCache + { + public static readonly Dictionary, int, BitReader, int, FieldMetaData, ColumnMetaData, Value32[], Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(long), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(float), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(uint), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(int), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(ushort), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(short), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(byte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(sbyte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(string), (record, info, id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -105,8 +128,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -214,37 +239,6 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC4Reader.cs b/DBCD.IO/Readers/WDC4Reader.cs index 84f7b3e..331d5f0 100644 --- a/DBCD.IO/Readers/WDC4Reader.cs +++ b/DBCD.IO/Readers/WDC4Reader.cs @@ -55,6 +55,29 @@ private static string getStringTableRecord(Dictionary stringTable, return stringTable[index]; } + private static class SingleReaderCache + { + public static readonly Dictionary, int, BitReader, int, FieldMetaData, ColumnMetaData, Value32[], Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(long), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(float), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(uint), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(int), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(ushort), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(short), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(byte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(sbyte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(string), (record, info, id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -105,8 +128,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, Data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -214,37 +239,6 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } - public IDBRow Clone() { return (IDBRow)MemberwiseClone(); diff --git a/DBCD.IO/Readers/WDC5Reader.cs b/DBCD.IO/Readers/WDC5Reader.cs index c1d29cc..af005b7 100644 --- a/DBCD.IO/Readers/WDC5Reader.cs +++ b/DBCD.IO/Readers/WDC5Reader.cs @@ -71,6 +71,29 @@ private static string getStringTableRecord(Dictionary stringTable, return stringTable[index]; } + private static class SingleReaderCache + { + public static readonly Dictionary, int, BitReader, int, FieldMetaData, ColumnMetaData, Value32[], Dictionary, Dictionary, BaseReader>> Readers = new() + { + { typeof(ulong), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(long), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(float), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(uint), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(int), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(ushort), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(short), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(byte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(sbyte), (record, info, id, data, _, fieldMeta, columnMeta, palletData, commonData, _, _) => info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)) }, + { typeof(string), (record, info, id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => + { + string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? + data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); + info.Setter.SetObject(record, stringValue); + } + } + }; + } + private static Dictionary, Dictionary, object>> arrayReaders = new Dictionary, Dictionary, object>> { [typeof(ulong[])] = (data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable) => GetFieldValueArray(data, fieldMeta, columnMeta, palletData, commonData), @@ -121,8 +144,10 @@ public void GetFields(FieldCache[] fields, T entry) else throw new Exception("Unhandled array type: " + typeof(T).Name); } + else if (SingleReaderCache.Readers.TryGetValue(info.FieldType, out var reader)) + reader(entry, info, Id, m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); else - ReadStronglyTyped(entry, info, Id, m_data, m_recordOffset, m_fieldMeta[fieldIndex], ColumnMeta[fieldIndex], PalletData[fieldIndex], CommonData[fieldIndex], m_reader.StringTable, m_reader); + throw new Exception("Unhandled field type: " + typeof(T).Name); } } @@ -229,37 +254,6 @@ private static string[] GetFieldValueStringArray(BitReader r, FieldMetaData fiel throw new Exception(string.Format("Unexpected compression type {0}", columnMeta.CompressionType)); } - - private static void ReadStronglyTyped(T record, FieldCache info, int id, BitReader data, int recordOffset, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData, Dictionary stringTable, BaseReader header) - { - // This is not very pretty, but it is required to avoid boxing the read values - if (info.FieldType == typeof(ulong)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(long)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(float)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(uint)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(int)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(ushort)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(short)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(byte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(sbyte)) - info.Setter.SetValue(record, GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData)); - else if (info.FieldType == typeof(string)) - { - string stringValue = header.Flags.HasFlagExt(DB2Flags.Sparse) ? - data.ReadCString() : getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData); - info.Setter.SetObject(record, stringValue); - } - else - throw new Exception("Unhandled field type: " + typeof(T).Name); - } public IDBRow Clone() { From f499e7fbfea4ca12663cf0f79e75f72331aaaed0 Mon Sep 17 00:00:00 2001 From: Ovahlord <18347559+ovahlord@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:29:04 +0200 Subject: [PATCH 4/5] Remove more boxing when reading Ids --- DBCD.IO/Readers/HTFXReader.cs | 5 ++++- DBCD.IO/Readers/WDB2Reader.cs | 6 +++++- DBCD.IO/Readers/WDB3Reader.cs | 5 ++++- DBCD.IO/Readers/WDB4Reader.cs | 5 ++++- DBCD.IO/Readers/WDB5Reader.cs | 5 ++++- DBCD.IO/Readers/WDB6Reader.cs | 5 ++++- DBCD.IO/Readers/WDC1Reader.cs | 5 ++++- DBCD.IO/Readers/WDC2Reader.cs | 5 ++++- DBCD.IO/Readers/WDC3Reader.cs | 5 ++++- DBCD.IO/Readers/WDC4Reader.cs | 5 ++++- DBCD.IO/Readers/WDC5Reader.cs | 5 ++++- 11 files changed, 45 insertions(+), 11 deletions(-) diff --git a/DBCD.IO/Readers/HTFXReader.cs b/DBCD.IO/Readers/HTFXReader.cs index 1e59a29..8e74bd1 100644 --- a/DBCD.IO/Readers/HTFXReader.cs +++ b/DBCD.IO/Readers/HTFXReader.cs @@ -71,7 +71,10 @@ public void GetFields(FieldCache[] fields, T entry) FieldCache info = fields[i]; if (info.IndexMapField) { - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDB2Reader.cs b/DBCD.IO/Readers/WDB2Reader.cs index 0f58ab8..e0a95c9 100644 --- a/DBCD.IO/Readers/WDB2Reader.cs +++ b/DBCD.IO/Readers/WDB2Reader.cs @@ -64,7 +64,11 @@ public void GetFields(FieldCache[] fields, T entry) if (info.IndexMapField) { Id = GetFieldValue(Data); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + + if (info.FieldType == typeof(T)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDB3Reader.cs b/DBCD.IO/Readers/WDB3Reader.cs index 8d7ad2f..468579c 100644 --- a/DBCD.IO/Readers/WDB3Reader.cs +++ b/DBCD.IO/Readers/WDB3Reader.cs @@ -84,7 +84,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDB4Reader.cs b/DBCD.IO/Readers/WDB4Reader.cs index f78038e..4cd63c8 100644 --- a/DBCD.IO/Readers/WDB4Reader.cs +++ b/DBCD.IO/Readers/WDB4Reader.cs @@ -84,7 +84,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDB5Reader.cs b/DBCD.IO/Readers/WDB5Reader.cs index 36e10b1..8ce17c5 100644 --- a/DBCD.IO/Readers/WDB5Reader.cs +++ b/DBCD.IO/Readers/WDB5Reader.cs @@ -91,7 +91,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(Data, m_fieldMeta[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDB6Reader.cs b/DBCD.IO/Readers/WDB6Reader.cs index c629353..b0f5d80 100644 --- a/DBCD.IO/Readers/WDB6Reader.cs +++ b/DBCD.IO/Readers/WDB6Reader.cs @@ -91,7 +91,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], CommonData?[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDC1Reader.cs b/DBCD.IO/Readers/WDC1Reader.cs index 6d99123..fc030f4 100644 --- a/DBCD.IO/Readers/WDC1Reader.cs +++ b/DBCD.IO/Readers/WDC1Reader.cs @@ -96,7 +96,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDC2Reader.cs b/DBCD.IO/Readers/WDC2Reader.cs index 065f0ef..6b13364 100644 --- a/DBCD.IO/Readers/WDC2Reader.cs +++ b/DBCD.IO/Readers/WDC2Reader.cs @@ -108,7 +108,10 @@ public void GetFields(FieldCache[] fields, T entry) Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); } - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDC3Reader.cs b/DBCD.IO/Readers/WDC3Reader.cs index ef7e7c6..426a76b 100644 --- a/DBCD.IO/Readers/WDC3Reader.cs +++ b/DBCD.IO/Readers/WDC3Reader.cs @@ -109,7 +109,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDC4Reader.cs b/DBCD.IO/Readers/WDC4Reader.cs index 331d5f0..1d5916e 100644 --- a/DBCD.IO/Readers/WDC4Reader.cs +++ b/DBCD.IO/Readers/WDC4Reader.cs @@ -109,7 +109,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, Data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } diff --git a/DBCD.IO/Readers/WDC5Reader.cs b/DBCD.IO/Readers/WDC5Reader.cs index af005b7..108ec35 100644 --- a/DBCD.IO/Readers/WDC5Reader.cs +++ b/DBCD.IO/Readers/WDC5Reader.cs @@ -125,7 +125,10 @@ public void GetFields(FieldCache[] fields, T entry) else Id = GetFieldValue(0, m_data, m_fieldMeta[i], ColumnMeta[i], PalletData[i], CommonData[i]); - info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); + if (info.FieldType == typeof(int)) + info.Setter.SetValue(entry, Id); + else + info.Setter.SetObject(entry, Convert.ChangeType(Id, info.FieldType)); continue; } From a68fb700f753d043cd444e8f9ad810c745251bea Mon Sep 17 00:00:00 2001 From: Ovahlord <18347559+ovahlord@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:33:46 +0200 Subject: [PATCH 5/5] Removed an unused dictionary --- DBCD.IO/Readers/WDC5Reader.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/DBCD.IO/Readers/WDC5Reader.cs b/DBCD.IO/Readers/WDC5Reader.cs index 108ec35..235cf76 100644 --- a/DBCD.IO/Readers/WDC5Reader.cs +++ b/DBCD.IO/Readers/WDC5Reader.cs @@ -44,22 +44,7 @@ public WDC5Row(BaseReader reader, BitReader data, int id, int refID, int recordI Id = id; } - - private static Dictionary, Dictionary, BaseReader, object>> simpleReaders = new Dictionary, Dictionary, BaseReader, object>> - { - [typeof(ulong)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(long)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(float)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(int)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(uint)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(short)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(ushort)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(sbyte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(byte)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData), - [typeof(string)] = (id, data, recordOffset, fieldMeta, columnMeta, palletData, commonData, stringTable, header) => header.Flags.HasFlagExt(DB2Flags.Sparse) ? data.ReadCString() : - getStringTableRecord(stringTable, recordOffset, id, data, fieldMeta, columnMeta, palletData, commonData), - }; - + private static string getStringTableRecord(Dictionary stringTable, int recordOffset, int id, BitReader data, FieldMetaData fieldMeta, ColumnMetaData columnMeta, Value32[] palletData, Dictionary commonData) { var index = recordOffset + (data.Position >> 3) + GetFieldValue(id, data, fieldMeta, columnMeta, palletData, commonData);