diff --git a/src/StarBreaker.Forge/DataForgeEnumDefinition.cs b/src/StarBreaker.Forge/DataForgeEnumDefinition.cs index 59e4d88..0602a3f 100644 --- a/src/StarBreaker.Forge/DataForgeEnumDefinition.cs +++ b/src/StarBreaker.Forge/DataForgeEnumDefinition.cs @@ -5,7 +5,7 @@ namespace StarBreaker.Forge; [StructLayout(LayoutKind.Sequential, Pack = 1)] public readonly record struct DataForgeEnumDefinition { - private readonly DataForgeStringId NameOffset; + private readonly DataForgeStringId2 NameOffset; public readonly ushort ValueCount; public readonly ushort FirstValueIndex; diff --git a/src/StarBreaker.Forge/DataForgePropertyDefinition.cs b/src/StarBreaker.Forge/DataForgePropertyDefinition.cs index 5885f72..70422d0 100644 --- a/src/StarBreaker.Forge/DataForgePropertyDefinition.cs +++ b/src/StarBreaker.Forge/DataForgePropertyDefinition.cs @@ -5,7 +5,7 @@ namespace StarBreaker.Forge; [StructLayout(LayoutKind.Sequential, Pack = 1)] public readonly record struct DataForgePropertyDefinition { - private readonly DataForgeStringId NameOffset; + private readonly DataForgeStringId2 NameOffset; public readonly ushort StructIndex; public readonly DataType DataType; public readonly ConversionType ConversionType; diff --git a/src/StarBreaker.Forge/DataForgeRecord.cs b/src/StarBreaker.Forge/DataForgeRecord.cs index 16aaa11..1c738d2 100644 --- a/src/StarBreaker.Forge/DataForgeRecord.cs +++ b/src/StarBreaker.Forge/DataForgeRecord.cs @@ -6,7 +6,7 @@ namespace StarBreaker.Forge; [StructLayout(LayoutKind.Sequential, Pack = 1)] public readonly record struct DataForgeRecord { - private readonly DataForgeStringId NameOffset; + private readonly DataForgeStringId2 NameOffset; public readonly DataForgeStringId FileNameOffset; public readonly int StructIndex; public readonly CigGuid Hash; diff --git a/src/StarBreaker.Forge/DataForgeStringId.cs b/src/StarBreaker.Forge/DataForgeStringId.cs index 8b6ecda..7c2303d 100644 --- a/src/StarBreaker.Forge/DataForgeStringId.cs +++ b/src/StarBreaker.Forge/DataForgeStringId.cs @@ -12,9 +12,16 @@ public readonly record struct DataForgeStringId public string Name => DebugGlobal.Database.GetString(this); public override string ToString() => Name; #endif +} - public DataForgeStringId(int id) - { - Id = id; - } +[StructLayout(LayoutKind.Sequential, Pack = 1)] +public readonly record struct DataForgeStringId2 +{ + // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable + public readonly int Id; + +#if DEBUG + public string Name => DebugGlobal.Database.GetString2(this); + public override string ToString() => Name; +#endif } \ No newline at end of file diff --git a/src/StarBreaker.Forge/DataForgeStructDefinition.cs b/src/StarBreaker.Forge/DataForgeStructDefinition.cs index 5dfb28e..315bb18 100644 --- a/src/StarBreaker.Forge/DataForgeStructDefinition.cs +++ b/src/StarBreaker.Forge/DataForgeStructDefinition.cs @@ -9,52 +9,51 @@ namespace StarBreaker.Forge; public readonly record struct DataForgeStructDefinition { private static readonly ConcurrentDictionary _propertiesCache = new(); - private readonly DataForgeStringId NameOffset; + private readonly DataForgeStringId2 NameOffset; public readonly uint ParentTypeIndex; public readonly ushort AttributeCount; public readonly ushort FirstAttributeIndex; public readonly uint NodeType; - + public string GetName(Database db) => db.GetString2(NameOffset); - [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CalculateSize(ReadOnlySpan structs, ReadOnlySpan properties) { var size = 0; foreach (var attribute in EnumerateProperties(structs, properties)) { - if (attribute.ConversionType == ConversionType.Attribute) - { - size += attribute.DataType switch - { - DataType.Reference => Unsafe.SizeOf(), - DataType.WeakPointer => Unsafe.SizeOf() * 2, - DataType.StrongPointer => Unsafe.SizeOf() * 2, - DataType.EnumChoice => Unsafe.SizeOf(), - DataType.Guid => Unsafe.SizeOf(), - DataType.Locale => Unsafe.SizeOf(), - DataType.Double => Unsafe.SizeOf(), - DataType.Single => Unsafe.SizeOf(), - DataType.String => Unsafe.SizeOf(), - DataType.UInt64 => Unsafe.SizeOf(), - DataType.UInt32 => Unsafe.SizeOf(), - DataType.UInt16 => Unsafe.SizeOf(), - DataType.Byte => Unsafe.SizeOf(), - DataType.Int64 => Unsafe.SizeOf(), - DataType.Int32 => Unsafe.SizeOf(), - DataType.Int16 => Unsafe.SizeOf(), - DataType.SByte => Unsafe.SizeOf(), - DataType.Boolean => Unsafe.SizeOf(), - DataType.Class => structs[attribute.StructIndex].CalculateSize(structs, properties), - _ => throw new ArgumentOutOfRangeException() - }; - } - else + if (attribute.ConversionType != ConversionType.Attribute) { //array count + array offset size += sizeof(int) * 2; + continue; } + + size += attribute.DataType switch + { + DataType.Reference => Unsafe.SizeOf(), + DataType.WeakPointer => Unsafe.SizeOf() * 2, + DataType.StrongPointer => Unsafe.SizeOf() * 2, + DataType.EnumChoice => Unsafe.SizeOf(), + DataType.Guid => Unsafe.SizeOf(), + DataType.Locale => Unsafe.SizeOf(), + DataType.Double => Unsafe.SizeOf(), + DataType.Single => Unsafe.SizeOf(), + DataType.String => Unsafe.SizeOf(), + DataType.UInt64 => Unsafe.SizeOf(), + DataType.UInt32 => Unsafe.SizeOf(), + DataType.UInt16 => Unsafe.SizeOf(), + DataType.Byte => Unsafe.SizeOf(), + DataType.Int64 => Unsafe.SizeOf(), + DataType.Int32 => Unsafe.SizeOf(), + DataType.Int16 => Unsafe.SizeOf(), + DataType.SByte => Unsafe.SizeOf(), + DataType.Boolean => Unsafe.SizeOf(), + DataType.Class => structs[attribute.StructIndex].CalculateSize(structs, properties), + _ => throw new ArgumentOutOfRangeException() + }; } return size; @@ -63,29 +62,29 @@ public int CalculateSize(ReadOnlySpan structs, ReadOn public DataForgePropertyDefinition[] EnumerateProperties( ReadOnlySpan structs, ReadOnlySpan properties - ) + ) { if (_propertiesCache.TryGetValue(this, out var cachedProperties)) return cachedProperties; - + var _properties = new List(); _properties.AddRange(properties.Slice(FirstAttributeIndex, AttributeCount)); - + var baseStruct = this; while (baseStruct.ParentTypeIndex != 0xFFFFFFFF) { baseStruct = structs[(int)baseStruct.ParentTypeIndex]; _properties.InsertRange(0, properties.Slice(baseStruct.FirstAttributeIndex, baseStruct.AttributeCount)); } - + var arr = _properties.ToArray(); _propertiesCache.TryAdd(this, arr); - + return arr; } - - #if DEBUG + +#if DEBUG public DataForgePropertyDefinition[] Properties => EnumerateProperties(DebugGlobal.Database.StructDefinitions, DebugGlobal.Database.PropertyDefinitions); public DataForgeStructDefinition? Parent => ParentTypeIndex == 0xffffffff ? null : DebugGlobal.Database.StructDefinitions[(int)ParentTypeIndex]; - #endif -} +#endif +} \ No newline at end of file diff --git a/src/StarBreaker.Forge/Database.cs b/src/StarBreaker.Forge/Database.cs index 098c07c..54f9894 100644 --- a/src/StarBreaker.Forge/Database.cs +++ b/src/StarBreaker.Forge/Database.cs @@ -129,7 +129,7 @@ public Database(string filePath, out int bytesRead) public SpanReader GetReader(int offset) => new(DataSection, offset - DataSectionOffset); public string GetString(DataForgeStringId id) => _cachedStrings[id.Id]; - public string GetString2(DataForgeStringId id) => _cachedStrings2[id.Id]; + public string GetString2(DataForgeStringId2 id) => _cachedStrings2[id.Id]; private static FrozenDictionary ReadStringTable(ReadOnlySpan span) { diff --git a/src/StarBreaker.Forge/XmlAttribute.cs b/src/StarBreaker.Forge/XmlAttribute.cs index df86674..505ffb2 100644 --- a/src/StarBreaker.Forge/XmlAttribute.cs +++ b/src/StarBreaker.Forge/XmlAttribute.cs @@ -29,6 +29,13 @@ public override void WriteTo(TextWriter writer) writer.Write('='); writer.Write('"'); + WriteValue(writer); + writer.Write('"'); + } + + private void WriteValue(TextWriter writer) + { + //we do this instead of passing the value directly to the writer to avoid boxing switch (Value) { case sbyte sb: @@ -84,7 +91,5 @@ public override void WriteTo(TextWriter writer) default: throw new NotImplementedException(); } - - writer.Write('"'); } } \ No newline at end of file diff --git a/src/StarBreaker.Forge/XmlNode.cs b/src/StarBreaker.Forge/XmlNode.cs index f3ff845..ce350b0 100644 --- a/src/StarBreaker.Forge/XmlNode.cs +++ b/src/StarBreaker.Forge/XmlNode.cs @@ -13,17 +13,14 @@ public sealed class XmlNode public XmlNode(string name) { _name = name; - _children = new List(); - _attributes = new List(); + _children = []; + _attributes = []; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AppendChild(XmlNode child) => _children.Add(child); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AppendAttribute(XmlAttribute xmlAttribute) => _attributes.Add(xmlAttribute); - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteTo(TextWriter writer, int depth) { for (var i = 0; i < depth; i++) diff --git a/src/StarBreaker.Tests/DataForgeTests.cs b/src/StarBreaker.Tests/DataForgeTests.cs index 12728fd..f49fbea 100644 --- a/src/StarBreaker.Tests/DataForgeTests.cs +++ b/src/StarBreaker.Tests/DataForgeTests.cs @@ -15,7 +15,7 @@ public void Setup() [Test] public void TestTagDatabase() { - var forge = new DataForge(@"D:\StarCitizenExport\Data\Game.dcb"); + var forge = new DataForge(@"D:\out\Data\Game.dcb"); var stringwriter = new StringWriter(); forge.X(@"libs/foundry/records/tagdatabase/tagdatabase.tagdatabase.xml", stringwriter);