mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-22 06:45:11 +00:00
Add inherent locking the the data source in wrappers
This commit is contained in:
@@ -167,7 +167,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
using FileStream fs = File.OpenWrite(filename);
|
||||
|
||||
// Read the data block
|
||||
var data = _dataSource.ReadFrom(offset, compressedSize, retainPosition: true);
|
||||
var data = ReadRangeFromSource(offset, compressedSize);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Read the data
|
||||
var lump = Lumps[index];
|
||||
var data = _dataSource.ReadFrom(lump.Offset, lump.Length, retainPosition: true);
|
||||
var data = ReadRangeFromSource(lump.Offset, lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Try to read the sector data
|
||||
var sectorData = _dataSource.ReadFrom(sectorDataOffset, (int)SectorSize, retainPosition: true);
|
||||
var sectorData = ReadRangeFromSource(sectorDataOffset, (int)SectorSize);
|
||||
if (sectorData == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
for (int i = 0; i < dataBlockOffsets.Count; i++)
|
||||
{
|
||||
int readSize = (int)Math.Min(BlockSize, fileSize);
|
||||
var data = _dataSource.ReadFrom((int)dataBlockOffsets[i], readSize, retainPosition: true);
|
||||
var data = ReadRangeFromSource((int)dataBlockOffsets[i], readSize);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
long outputFileSize = file.UncompressedSize;
|
||||
|
||||
// Read the compressed data directly
|
||||
var compressedData = _dataSource.ReadFrom((int)fileOffset, (int)fileSize, retainPosition: true);
|
||||
var compressedData = ReadRangeFromSource((int)fileOffset, (int)fileSize);
|
||||
if (compressedData == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return false;
|
||||
|
||||
// Read in the data as an array
|
||||
byte[]? contents = _dataSource.ReadFrom(DataOffset, (int)compressedSize, retainPosition: true);
|
||||
byte[]? contents = ReadRangeFromSource(DataOffset, (int)compressedSize);
|
||||
if (contents == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return false;
|
||||
|
||||
// Read in the data as an array
|
||||
byte[]? contents = _dataSource.ReadFrom(12, (int)compressedSize, retainPosition: true);
|
||||
byte[]? contents = ReadRangeFromSource(12, (int)compressedSize);
|
||||
if (contents == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return false;
|
||||
|
||||
// Read in the data as an array
|
||||
byte[]? contents = _dataSource.ReadFrom(14, (int)compressedSize, retainPosition: true);
|
||||
byte[]? contents = ReadRangeFromSource(14, (int)compressedSize);
|
||||
if (contents == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return [];
|
||||
|
||||
// Read the entry data and return
|
||||
return _dataSource.ReadFrom(offset, length, retainPosition: true);
|
||||
return ReadRangeFromSource(offset, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -315,7 +315,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (length == -1)
|
||||
length = Length;
|
||||
|
||||
return _dataSource.ReadFrom(rangeStart, (int)length, retainPosition: true);
|
||||
return ReadRangeFromSource(rangeStart, (int)length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -51,59 +51,56 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null)
|
||||
return -1;
|
||||
|
||||
lock (_sourceDataLock)
|
||||
// Search through the segments table to find the furthest
|
||||
long endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
{
|
||||
// Search through the segments table to find the furthest
|
||||
long endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
{
|
||||
// Get end of segment data
|
||||
long offset = (entry.Offset * (1 << Header.SegmentAlignmentShiftCount)) + entry.Length;
|
||||
// Get end of segment data
|
||||
long offset = (entry.Offset * (1 << Header.SegmentAlignmentShiftCount)) + entry.Length;
|
||||
|
||||
// Read and find the end of the relocation data
|
||||
// Read and find the end of the relocation data
|
||||
#if NET20 || NET35
|
||||
if ((entry.FlagWord & SegmentTableEntryFlag.RELOCINFO) != 0)
|
||||
#else
|
||||
if (entry.FlagWord.HasFlag(SegmentTableEntryFlag.RELOCINFO))
|
||||
if (entry.FlagWord.HasFlag(SegmentTableEntryFlag.RELOCINFO))
|
||||
#endif
|
||||
{
|
||||
_dataSource.Seek(offset, SeekOrigin.Begin);
|
||||
var relocationData = Deserializers.NewExecutable.ParsePerSegmentData(_dataSource);
|
||||
{
|
||||
_dataSource.Seek(offset, SeekOrigin.Begin);
|
||||
var relocationData = Deserializers.NewExecutable.ParsePerSegmentData(_dataSource);
|
||||
|
||||
offset = _dataSource.Position;
|
||||
}
|
||||
offset = _dataSource.Position;
|
||||
}
|
||||
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// Adjust the position of the data by 705 bytes
|
||||
// TODO: Investigate what the byte data is
|
||||
endOfSectionData += 705;
|
||||
|
||||
// Cache and return the position
|
||||
_overlayAddress = endOfSectionData;
|
||||
return _overlayAddress.Value;
|
||||
}
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// Adjust the position of the data by 705 bytes
|
||||
// TODO: Investigate what the byte data is
|
||||
endOfSectionData += 705;
|
||||
|
||||
// Cache and return the position
|
||||
_overlayAddress = endOfSectionData;
|
||||
return _overlayAddress.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,12 +143,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// Otherwise, cache and return the data
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom((int)endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
}
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = ReadRangeFromSource((int)endOfSectionData, (int)overlayLength);
|
||||
return _overlayData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,16 +215,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = ReadRangeFromSource(endOfStubHeader, lengthOfStubExecutableData);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,11 +270,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
private readonly object _stubExecutableDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for reading from the source
|
||||
/// </summary>
|
||||
private readonly object _sourceDataLock = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@@ -654,7 +640,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return [];
|
||||
|
||||
// Read the resource data and return
|
||||
return _dataSource.ReadFrom(offset, length, retainPosition: true);
|
||||
return ReadRangeFromSource(offset, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -746,7 +732,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return [];
|
||||
|
||||
// Read the segment data and return
|
||||
return _dataSource.ReadFrom(offset, length, retainPosition: true);
|
||||
return ReadRangeFromSource(offset, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -816,7 +802,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (length == -1)
|
||||
length = Length;
|
||||
|
||||
return _dataSource.ReadFrom(rangeStart, (int)length, retainPosition: true);
|
||||
return ReadRangeFromSource(rangeStart, (int)length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Read the item data
|
||||
var directoryItem = DirectoryItems[index];
|
||||
var data = _dataSource.ReadFrom((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength, retainPosition: true);
|
||||
var data = ReadRangeFromSource((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
using FileStream fs = File.OpenWrite(filename);
|
||||
|
||||
// Read the data block
|
||||
var data = _dataSource.ReadFrom(offset, size, retainPosition: true);
|
||||
var data = ReadRangeFromSource(offset, size);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -42,11 +42,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached dictionary
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
}
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,11 +87,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// Read the first 128 bytes of the entry point
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_entryPointData = _dataSource.ReadFrom(entryPointAddress, length: 128, retainPosition: true);
|
||||
return _entryPointData;
|
||||
}
|
||||
_entryPointData = ReadRangeFromSource(entryPointAddress, length: 128);
|
||||
return _entryPointData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,11 +139,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _headerPaddingData;
|
||||
}
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_headerPaddingData = _dataSource.ReadFrom((int)headerStartAddress, headerLength, retainPosition: true);
|
||||
return _headerPaddingData;
|
||||
}
|
||||
_headerPaddingData = ReadRangeFromSource((int)headerStartAddress, headerLength);
|
||||
return _headerPaddingData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,11 +188,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_headerPaddingStrings = _dataSource.ReadStringsFrom((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
_headerPaddingStrings = _dataSource.ReadStringsFrom((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,12 +309,9 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// Otherwise, cache and return the data
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom(endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
}
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = ReadRangeFromSource(endOfSectionData, (int)overlayLength);
|
||||
return _overlayData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -432,16 +417,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = ReadRangeFromSource(endOfStubHeader, lengthOfStubExecutableData);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -777,11 +759,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
private AssemblyManifest? _assemblyManifest = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for reading from the source
|
||||
/// </summary>
|
||||
private readonly object _sourceDataLock = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@@ -1035,7 +1012,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
byte[]? entryData;
|
||||
try
|
||||
{
|
||||
entryData = _dataSource.ReadFrom((int)address, (int)size, retainPosition: true);
|
||||
entryData = ReadRangeFromSource((int)address, (int)size);
|
||||
if (entryData == null || entryData.Length < 4)
|
||||
continue;
|
||||
}
|
||||
@@ -1545,7 +1522,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Read the section into a local array
|
||||
int sectionLength = (int)section.VirtualSize;
|
||||
byte[]? sectionData = source.ReadFrom(offset, sectionLength, retainPosition: true);
|
||||
byte[]? sectionData;
|
||||
lock (source)
|
||||
{
|
||||
sectionData = source.ReadFrom(offset, sectionLength, retainPosition: true);
|
||||
}
|
||||
|
||||
// Parse the section header
|
||||
var header = WiseSectionHeader.Create(sectionData, 0);
|
||||
@@ -2209,22 +2190,20 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Set the section size
|
||||
uint size = section.SizeOfRawData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Create the section data array if we have to
|
||||
_sectionData ??= new byte[SectionNames.Length][];
|
||||
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_sectionData[index] != null && _sectionData[index].Length > 0)
|
||||
return _sectionData[index];
|
||||
// Create the section data array if we have to
|
||||
_sectionData ??= new byte[SectionNames.Length][];
|
||||
|
||||
// Populate the raw section data based on the source
|
||||
byte[]? sectionData = _dataSource.ReadFrom((int)address, (int)size, retainPosition: true);
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_sectionData[index] != null && _sectionData[index].Length > 0)
|
||||
return _sectionData[index];
|
||||
|
||||
// Cache and return the section data, even if null
|
||||
_sectionData[index] = sectionData ?? [];
|
||||
return sectionData;
|
||||
}
|
||||
// Populate the raw section data based on the source
|
||||
byte[]? sectionData = ReadRangeFromSource((int)address, (int)size);
|
||||
|
||||
// Cache and return the section data, even if null
|
||||
_sectionData[index] = sectionData ?? [];
|
||||
return sectionData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2304,15 +2283,13 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Set the section size
|
||||
uint size = section.SizeOfRawData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Populate the section string data based on the source
|
||||
List<string>? sectionStringData = _dataSource.ReadStringsFrom((int)address, (int)size);
|
||||
|
||||
// Cache and return the section string data, even if null
|
||||
_sectionStringData[index] = sectionStringData ?? [];
|
||||
return sectionStringData;
|
||||
}
|
||||
// Populate the section string data based on the source
|
||||
List<string>? sectionStringData = _dataSource.ReadStringsFrom((int)address, (int)size);
|
||||
|
||||
// Cache and return the section string data, even if null
|
||||
_sectionStringData[index] = sectionStringData ?? [];
|
||||
return sectionStringData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2382,22 +2359,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Create the table data array if we have to
|
||||
_tableData ??= new byte[16][];
|
||||
// Create the table data array if we have to
|
||||
_tableData ??= new byte[16][];
|
||||
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_tableData[index] != null && _tableData[index].Length > 0)
|
||||
return _tableData[index];
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_tableData[index] != null && _tableData[index].Length > 0)
|
||||
return _tableData[index];
|
||||
|
||||
// Populate the raw table data based on the source
|
||||
byte[]? tableData = _dataSource.ReadFrom((int)address, (int)size, retainPosition: true);
|
||||
// Populate the raw table data based on the source
|
||||
byte[]? tableData = ReadRangeFromSource((int)address, (int)size);
|
||||
|
||||
// Cache and return the table data, even if null
|
||||
_tableData[index] = tableData ?? [];
|
||||
return tableData;
|
||||
}
|
||||
// Cache and return the table data, even if null
|
||||
_tableData[index] = tableData ?? [];
|
||||
return tableData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2427,22 +2401,19 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (address == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Create the table string array if we have to
|
||||
_tableStringData ??= new List<string>[16];
|
||||
// Create the table string array if we have to
|
||||
_tableStringData ??= new List<string>[16];
|
||||
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_tableStringData[index] != null && _tableStringData[index].Count > 0)
|
||||
return _tableStringData[index];
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_tableStringData[index] != null && _tableStringData[index].Count > 0)
|
||||
return _tableStringData[index];
|
||||
|
||||
// Populate the table string data based on the source
|
||||
List<string>? tableStringData = _dataSource.ReadStringsFrom((int)address, (int)size);
|
||||
// Populate the table string data based on the source
|
||||
List<string>? tableStringData = _dataSource.ReadStringsFrom((int)address, (int)size);
|
||||
|
||||
// Cache and return the table string data, even if null
|
||||
_tableStringData[index] = tableStringData ?? [];
|
||||
return tableStringData;
|
||||
}
|
||||
// Cache and return the table string data, even if null
|
||||
_tableStringData[index] = tableStringData ?? [];
|
||||
return tableStringData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
// Read the entire compressed data
|
||||
int compressedDataOffset = (int)CompressedDataOffset;
|
||||
long compressedDataLength = Length - compressedDataOffset;
|
||||
var compressedData = _dataSource.ReadFrom(compressedDataOffset, (int)compressedDataLength, retainPosition: true);
|
||||
var compressedData = ReadRangeFromSource(compressedDataOffset, (int)compressedDataLength);
|
||||
|
||||
// Print a debug reminder
|
||||
if (includeDebug) Console.WriteLine("Quantum archive extraction is unsupported");
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
long outputFileSize = GetUncompressedSize(index);
|
||||
|
||||
// Read the compressed data directly
|
||||
var compressedData = _dataSource.ReadFrom((int)fileOffset, (int)fileSize, retainPosition: true);
|
||||
var compressedData = ReadRangeFromSource((int)fileOffset, (int)fileSize);
|
||||
if (compressedData == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Read the data
|
||||
var lump = Lumps[index];
|
||||
var data = _dataSource.ReadFrom(lump.Offset, lump.Length, retainPosition: true);
|
||||
var data = ReadRangeFromSource(lump.Offset, lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
// Read the data -- TODO: Handle uncompressed lumps (see BSP.ExtractTexture)
|
||||
var lump = DirEntries[index];
|
||||
var data = _dataSource.ReadFrom((int)lump.Offset, (int)lump.Length, retainPosition: true);
|
||||
var data = ReadRangeFromSource((int)lump.Offset, (int)lump.Length);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Streams;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -57,6 +58,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Lock for accessing <see cref="_dataSource"/>
|
||||
/// </summary>
|
||||
protected readonly object _dataSourceLock = new();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@@ -89,6 +95,33 @@ namespace SabreTools.Serialization.Wrappers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
|
||||
/// <summary>
|
||||
/// Read a number of bytes from an offset fomr the data source, if possible
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset within the data source to start reading</param>
|
||||
/// <param name="length">Number of bytes to read from the offset</param>
|
||||
/// <returns>Filled byte array on success, null on error</returns>
|
||||
/// <remarks>
|
||||
/// This method locks the data source to avoid potential conflicts in reading
|
||||
/// from the data source. This should be the preferred way of reading in cases
|
||||
/// where there may be multiple threads accessing the wrapper.
|
||||
///
|
||||
/// This method will return a null array if the length is greater than what is left
|
||||
/// in the stream. This is different behavior than a normal stream read that would
|
||||
/// attempt to read as much as possible, returning the amount of bytes read.
|
||||
/// </remarks>
|
||||
protected byte[]? ReadRangeFromSource(long offset, int length)
|
||||
{
|
||||
lock (_dataSourceLock)
|
||||
{
|
||||
return _dataSource.ReadFrom(offset, length, retainPosition: true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region JSON Export
|
||||
|
||||
#if NETCOREAPP
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return false;
|
||||
|
||||
// Load the item data
|
||||
var data = _dataSource.ReadFrom((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength, retainPosition: true);
|
||||
var data = ReadRangeFromSource((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user