Skip to content

Commit

Permalink
Merge pull request #47 from Soreepeong/fix/excel-rowparser-threadsafe
Browse files Browse the repository at this point in the history
Make RowParser thread safe
  • Loading branch information
NotAdam authored Jun 25, 2022
2 parents 2040e26 + ac115ab commit 4bf82be
Showing 1 changed file with 32 additions and 43 deletions.
75 changes: 32 additions & 43 deletions src/Lumina/Excel/RowParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ namespace Lumina.Excel
public class RowParser
{
private readonly ExcelSheetImpl _sheet;
private readonly ExcelDataFile _dataFile;
private readonly Dictionary< uint, ExcelDataOffset > _rowData;
private readonly BinaryReader _reader;

private ExcelDataOffset _offset;
private ExcelDataRowHeader _rowHeader;
Expand All @@ -25,7 +26,6 @@ public class RowParser
public uint SubRowId;
public uint RowCount => _rowHeader.RowCount;

private MemoryStream Stream => _dataFile.FileStream;

/// <summary>
/// Provides access to the base data generated for a sheet
Expand All @@ -35,7 +35,8 @@ public class RowParser
public RowParser( ExcelSheetImpl sheet, ExcelDataFile dataFile )
{
_sheet = sheet;
_dataFile = dataFile;
_rowData = dataFile.RowData;
_reader = new BinaryReader( new MemoryStream( dataFile.Data, false ) );
}

public RowParser( ExcelSheetImpl sheet, ExcelDataFile dataFile, uint row )
Expand Down Expand Up @@ -72,18 +73,16 @@ public bool TrySeekToRow( uint row )
{
RowId = row;

if( !_dataFile.RowData.TryGetValue( RowId, out var offset ) )
if( !_rowData.TryGetValue( RowId, out var offset ) )
{
return false;
}

_offset = offset;

var br = _dataFile.Reader;
_reader.BaseStream.Position = _offset.Offset;

Stream.Position = _offset.Offset;

_rowHeader = br.ReadStructure< ExcelDataRowHeader >();
_rowHeader = _reader.ReadStructure< ExcelDataRowHeader >();

if( BitConverter.IsLittleEndian )
{
Expand Down Expand Up @@ -151,11 +150,9 @@ public long CalculateSubRowOffset( uint subRow )
/// <returns>A copy of the read bytes</returns>
public byte[] ReadBytes( int offset, int count )
{
var br = _dataFile.Reader;

Stream.Position = _rowOffset + offset;
_reader.BaseStream.Position = _rowOffset + offset;

return br.ReadBytes( count );
return _reader.ReadBytes( count );
}

/// <summary>
Expand All @@ -166,11 +163,9 @@ public byte[] ReadBytes( int offset, int count )
/// <returns>The read structure filled from the row data</returns>
public T ReadStructure< T >( int offset ) where T : struct
{
var br = _dataFile.Reader;

Stream.Position = _rowOffset + offset;
_reader.BaseStream.Position = _rowOffset + offset;

return br.ReadStructure< T >();
return _reader.ReadStructure< T >();
}

/// <summary>
Expand All @@ -182,11 +177,9 @@ public T ReadStructure< T >( int offset ) where T : struct
/// <returns>The read structures filled from the row data</returns>
public List< T > ReadStructures< T >( int offset, int count ) where T : struct
{
var br = _dataFile.Reader;
_reader.BaseStream.Position = _rowOffset + offset;

Stream.Position = _rowOffset + offset;

return br.ReadStructures< T >( count );
return _reader.ReadStructures< T >( count );
}

/// <summary>
Expand All @@ -198,11 +191,9 @@ public List< T > ReadStructures< T >( int offset, int count ) where T : struct
/// <returns>The read structures filled from the row data</returns>
public T[] ReadStructuresAsArray< T >( int offset, int count ) where T : struct
{
var br = _dataFile.Reader;

Stream.Position = _rowOffset + offset;
_reader.BaseStream.Position = _rowOffset + offset;

return br.ReadStructuresAsArray< T >( count );
return _reader.ReadStructuresAsArray< T >( count );
}

// bit faster way of finding _rsv_ keys without having to convert the whole thing to a string first and shit
Expand Down Expand Up @@ -242,16 +233,14 @@ public T[] ReadStructuresAsArray< T >( int offset, int count ) where T : struct

private object ReadFieldInternal( ExcelColumnDataType type )
{
var br = _dataFile.Reader;

object? data = null;

switch( type )
{
case ExcelColumnDataType.String:
{
var stringOffset = br.ReadUInt32();
var raw = br.ReadRawOffsetData( _rowOffset + _sheet.Header.DataOffset + stringOffset );
var stringOffset = _reader.ReadUInt32();
var raw = _reader.ReadRawOffsetData( _rowOffset + _sheet.Header.DataOffset + stringOffset );

if( Sheet.GameData.Options.ResolveKnownRsvSheetValues )
{
Expand All @@ -268,54 +257,54 @@ private object ReadFieldInternal( ExcelColumnDataType type )
}
case ExcelColumnDataType.Bool:
{
data = br.ReadByte() != 0;
data = _reader.ReadByte() != 0;
break;
}
case ExcelColumnDataType.Int8:
{
data = br.ReadSByte();
data = _reader.ReadSByte();
break;
}
case ExcelColumnDataType.UInt8:
{
data = br.ReadByte();
data = _reader.ReadByte();
break;
}
case ExcelColumnDataType.Int16:
{
data = br.ReadInt16();
data = _reader.ReadInt16();
break;
}
case ExcelColumnDataType.UInt16:
{
data = br.ReadUInt16();
data = _reader.ReadUInt16();
break;
}
case ExcelColumnDataType.Int32:
{
data = br.ReadInt32();
data = _reader.ReadInt32();
break;
}
case ExcelColumnDataType.UInt32:
{
data = br.ReadUInt32();
data = _reader.ReadUInt32();
break;
}
// case ExcelColumnDataType.Unk:
// break;
case ExcelColumnDataType.Float32:
{
data = br.ReadSingle();
data = _reader.ReadSingle();
break;
}
case ExcelColumnDataType.Int64:
{
data = br.ReadUInt64();
data = _reader.ReadUInt64();
break;
}
case ExcelColumnDataType.UInt64:
{
data = br.ReadUInt64();
data = _reader.ReadUInt64();
break;
}
// case ExcelColumnDataType.Unk2:
Expand All @@ -332,7 +321,7 @@ private object ReadFieldInternal( ExcelColumnDataType type )
var shift = (int)type - (int)ExcelColumnDataType.PackedBool0;
var bit = 1 << shift;

var rawData = br.ReadByte();
var rawData = _reader.ReadByte();

data = ( rawData & bit ) == bit;

Expand Down Expand Up @@ -404,7 +393,7 @@ private byte GetBitPosition( byte flag )
/// <returns>The read data contained in the provided type</returns>
public T? ReadOffset< T >( ushort offset, byte bit = 0 )
{
Stream.Position = _rowOffset + offset;
_reader.BaseStream.Position = _rowOffset + offset;

if( bit == 0 )
{
Expand All @@ -425,7 +414,7 @@ private byte GetBitPosition( byte flag )
/// <returns>The read data contained in the provided type</returns>
public T? ReadOffset< T >( int offset, ExcelColumnDataType type )
{
Stream.Position = _rowOffset + offset;
_reader.BaseStream.Position = _rowOffset + offset;

return ReadField< T >( type );
}
Expand All @@ -445,7 +434,7 @@ private byte GetBitPosition( byte flag )

var col = _sheet.Columns[ column ];

Stream.Position = _rowOffset + col.Offset;
_reader.BaseStream.Position = _rowOffset + col.Offset;

return ReadField< T >( col.Type );
}
Expand All @@ -468,7 +457,7 @@ private byte GetBitPosition( byte flag )

var col = _sheet.Columns[ column ];

Stream.Position = _rowOffset + col.Offset;
_reader.BaseStream.Position = _rowOffset + col.Offset;

return ReadFieldInternal( col.Type );
}
Expand Down

0 comments on commit 4bf82be

Please sign in to comment.