Cache more properties using the field keyword

This commit is contained in:
Matt Nadareski
2025-11-14 10:14:50 -05:00
parent 0638998773
commit 60e46e580d
7 changed files with 98 additions and 45 deletions

View File

@@ -27,13 +27,21 @@ namespace SabreTools.Serialization.Wrappers
{
get
{
// Use the cached value, if it exists
if (field != null)
return field;
// Find the type and version record, if possible
var record = Array.Find(Records, r => r.RecordType == RecordType.TypeAndVersion);
if (record is TypeAndVersionRecord tavr)
return tavr.VersionNumber.ToString();
{
field = tavr.VersionNumber.ToString();
return field;
}
return null;
return field;
}
}
} = null;
#endregion

View File

@@ -41,7 +41,7 @@ namespace SabreTools.Serialization.Wrappers
return field;
// If there are no directory entries
if (DirectoryEntries == null || DirectoryEntries.Length == 0)
if (DirectoryEntries.Length == 0)
return [];
// Get the mini stream offset from root object
@@ -56,12 +56,12 @@ namespace SabreTools.Serialization.Wrappers
/// <summary>
/// Normal sector size in bytes
/// </summary>
public long SectorSize => (long)Math.Pow(2, Header?.SectorShift ?? 0);
public long SectorSize => (long)Math.Pow(2, Header.SectorShift);
/// <summary>
/// Mini sector size in bytes
/// </summary>
public long MiniSectorSize => (long)Math.Pow(2, Header?.MiniSectorShift ?? 0);
public long MiniSectorSize => (long)Math.Pow(2, Header.MiniSectorShift);
#endregion

View File

@@ -24,7 +24,7 @@ namespace SabreTools.Serialization.Wrappers
{
get
{
// Use the cached value if we have it
// Use the cached value, if it exists
if (field != null)
return field;
@@ -48,14 +48,10 @@ namespace SabreTools.Serialization.Wrappers
{
get
{
// Use the cached value if we have it
// Use the cached value, if it exists
if (field != null)
return field;
// If we don't have a required property
if (Model.DirectoryEntries == null || Model.DirectoryMapEntries == null)
return null;
// Otherwise, scan and build the files
var files = new List<FileInfo>();
for (int i = 0; i < Model.DirectoryEntries.Length; i++)
@@ -82,7 +78,7 @@ namespace SabreTools.Serialization.Wrappers
Encrypted = directoryEntry.DirectoryFlags.HasFlag(Data.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED),
#endif
};
var pathParts = new List<string> { Model.DirectoryNames![directoryEntry.NameOffset] ?? string.Empty };
var pathParts = new List<string> { Model.DirectoryNames[directoryEntry.NameOffset] ?? string.Empty };
var blockEntries = new List<Data.Models.GCF.BlockEntry>();
// Traverse the parent tree
@@ -90,7 +86,7 @@ namespace SabreTools.Serialization.Wrappers
while (index != 0xFFFFFFFF)
{
var parentDirectoryEntry = Model.DirectoryEntries[index];
pathParts.Add(Model.DirectoryNames![parentDirectoryEntry.NameOffset] ?? string.Empty);
pathParts.Add(Model.DirectoryNames[parentDirectoryEntry.NameOffset] ?? string.Empty);
index = parentDirectoryEntry.ParentIndex;
}

View File

@@ -27,11 +27,16 @@ namespace SabreTools.Serialization.Wrappers
if (!IsTorrentGZip)
return null;
// Use the cached value, if it exists
if (field != null)
return field;
// CRC-32 is the second packed field
int extraIndex = 0x10;
return Header.ExtraFieldBytes.ReadBytes(ref extraIndex, 0x04);
field = Header.ExtraFieldBytes.ReadBytes(ref extraIndex, 0x04);
return field;
}
}
} = null;
/// <summary>
/// Content MD5 as stored in the extra field
@@ -45,11 +50,16 @@ namespace SabreTools.Serialization.Wrappers
if (!IsTorrentGZip)
return null;
// Use the cached value, if it exists
if (field != null)
return field;
// MD5 is the first packed field
int extraIndex = 0x00;
return Header.ExtraFieldBytes.ReadBytes(ref extraIndex, 0x10);
field = Header.ExtraFieldBytes.ReadBytes(ref extraIndex, 0x10);
return field;
}
}
} = null;
/// <summary>
/// Content size as stored in the extra field
@@ -63,11 +73,16 @@ namespace SabreTools.Serialization.Wrappers
if (!IsTorrentGZip)
return 0;
// MD5 is the first packed field
int extraIndex = 0x00;
return Header.ExtraFieldBytes.ReadUInt64LittleEndian(ref extraIndex);
// Use the cached value, if it exists
if (field > 0)
return field;
// Size is the third packed field
int extraIndex = 0x14;
field = Header.ExtraFieldBytes.ReadUInt64LittleEndian(ref extraIndex);
return field;
}
}
} = 0;
/// <summary>
/// Offset to the compressed data
@@ -77,6 +92,7 @@ namespace SabreTools.Serialization.Wrappers
{
get
{
// Use the cached value, if it exists
if (field > -1)
return field;

View File

@@ -17,16 +17,49 @@ namespace SabreTools.Serialization.Wrappers
#region Extension Properties
/// <inheritdoc cref="Executable.ObjectPageMap"/>
public InformationBlock? InformationBlock => Model.InformationBlock;
public InformationBlock InformationBlock => Model.InformationBlock;
/// <inheritdoc cref="Executable.ObjectPageMap"/>
public ObjectPageMapEntry[]? ObjectPageMap => Model.ObjectPageMap;
public ObjectPageMapEntry[] ObjectPageMap => Model.ObjectPageMap;
/// <inheritdoc cref="Executable.ResourceTable"/>
public ResourceTableEntry[]? ResourceTable => Model.ResourceTable;
public ResourceTableEntry[] ResourceTable => Model.ResourceTable;
/// <inheritdoc cref="Executable.Stub"/>
public Data.Models.MSDOS.Executable? Stub => Model.Stub;
public Data.Models.MSDOS.Executable Stub => Model.Stub;
/// <summary>
/// Stub executable data, if it exists
/// </summary>
public byte[] StubExecutableData
{
get
{
lock (_stubExecutableDataLock)
{
// If we already have cached data, just use that immediately
if (field != null)
return field;
// Populate the raw stub executable data based on the source
int endOfStubHeader = 0x40;
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
field = ReadRangeFromSource(endOfStubHeader, lengthOfStubExecutableData);
// Cache and return the stub executable data, even if null
return field;
}
}
} = null;
#endregion
#region Instance Variables
/// <summary>
/// Lock object for <see cref="StubExecutableData"/>
/// </summary>
private readonly object _stubExecutableDataLock = new();
#endregion

View File

@@ -34,19 +34,19 @@ namespace SabreTools.Serialization.Wrappers
lock (_debugDataLock)
{
// Use the cached data if possible
if (_debugData.Count != 0)
return _debugData;
if (field.Count != 0)
return field;
// If we have no resource table, just return
if (DebugDirectoryTable == null || DebugDirectoryTable.Length == 0)
return _debugData;
return field;
// Otherwise, build and return the cached dictionary
ParseDebugTable();
return _debugData;
field = ParseDebugTable();
return field;
}
}
}
} = [];
/// <inheritdoc cref="Models.PortableExecutable.DebugData.Table.Table"/>
public Data.Models.PortableExecutable.DebugData.Entry[]? DebugDirectoryTable
@@ -822,12 +822,7 @@ namespace SabreTools.Serialization.Wrappers
#region Instance Variables
/// <summary>
/// Cached debug data
/// </summary>
private readonly Dictionary<int, object> _debugData = [];
/// <summary>
/// Lock object for <see cref="_debugData"/>
/// Lock object for <see cref="DebugData"/>
/// </summary>
private readonly object _debugDataLock = new();
@@ -1200,11 +1195,14 @@ namespace SabreTools.Serialization.Wrappers
/// <summary>
/// Parse the debug directory table information
/// </summary>
private void ParseDebugTable()
private Dictionary<int, object> ParseDebugTable()
{
// If there is no debug table
if (DebugDirectoryTable == null || DebugDirectoryTable.Length == 0)
return;
return [];
// Create a new debug table
Dictionary<int, object> debugData = [];
// Loop through all debug table entries
for (int i = 0; i < DebugDirectoryTable.Length; i++)
@@ -1223,7 +1221,7 @@ namespace SabreTools.Serialization.Wrappers
}
catch (EndOfStreamException)
{
return;
return debugData;
}
// If we have CodeView debug data, try to parse it
@@ -1242,7 +1240,7 @@ namespace SabreTools.Serialization.Wrappers
var nb10ProgramDatabase = entryData.ParseNB10ProgramDatabase(ref offset);
if (nb10ProgramDatabase != null)
{
_debugData[i] = nb10ProgramDatabase;
debugData[i] = nb10ProgramDatabase;
continue;
}
}
@@ -1253,16 +1251,18 @@ namespace SabreTools.Serialization.Wrappers
var rsdsProgramDatabase = entryData.ParseRSDSProgramDatabase(ref offset);
if (rsdsProgramDatabase != null)
{
_debugData[i] = rsdsProgramDatabase;
debugData[i] = rsdsProgramDatabase;
continue;
}
}
}
else
{
_debugData[i] = entryData;
debugData[i] = entryData;
}
}
return debugData;
}
#endregion

View File

@@ -22,7 +22,7 @@ namespace SabreTools.Serialization.Wrappers
{
get
{
// Use the cached value if we have it
// Use the cached value, if it exists
if (field != null)
return field;