Even better objects #39

Merged
mahalex merged 10 commits from dev/even-better-objects into master 2025-04-14 19:03:42 +00:00
2 changed files with 54 additions and 28 deletions
Showing only changes of commit 919014a109 - Show all commits

View File

@ -30,9 +30,15 @@ namespace MatFileHandler
/// </summary> /// </summary>
/// <param name="reader">Input reader.</param> /// <param name="reader">Input reader.</param>
/// <returns>Data element.</returns> /// <returns>Data element.</returns>
public DataElement Read(BinaryReader reader) public DataElement? Read(BinaryReader reader)
{ {
var (dataReader, tag) = ReadTag(reader); var maybeTagPair = ReadTag(reader);
if (maybeTagPair is not { } tagPair)
{
return null;
}
var (dataReader, tag) = tagPair;
var result = tag.Type switch var result = tag.Type switch
{ {
@ -167,9 +173,31 @@ namespace MatFileHandler
}; };
} }
private static (BinaryReader reader, Tag tag) ReadTag(BinaryReader reader) private static int? TryReadInt32(BinaryReader reader)
{ {
var type = reader.ReadInt32(); var buffer = new byte[4];
var position = 0;
while (position < 4)
{
var actually = reader.BaseStream.Read(buffer, position, 4 - position);
if (actually == 0)
{
return null;
}
position += actually;
}
return BitConverter.ToInt32(buffer, 0);
}
private static (BinaryReader reader, Tag tag)? ReadTag(BinaryReader reader)
{
var maybeType = TryReadInt32(reader);
if (maybeType is not int type)
{
return null;
}
var typeHi = type >> 16; var typeHi = type >> 16;
if (typeHi == 0) if (typeHi == 0)
{ {
@ -214,7 +242,7 @@ namespace MatFileHandler
var classNameElement = Read(reader) as MiNum<sbyte> ?? var classNameElement = Read(reader) as MiNum<sbyte> ??
throw new HandlerException("Unexpected type in class name."); throw new HandlerException("Unexpected type in class name.");
var className = ReadName(classNameElement); var className = ReadName(classNameElement);
var dataElement = Read(reader); var dataElement = Read(reader) ?? throw new HandlerException("Missing opaque data element.");
var data = ReadData(dataElement); var data = ReadData(dataElement);
if (data is MatNumericalArrayOf<uint> linkElement) if (data is MatNumericalArrayOf<uint> linkElement)
{ {
@ -246,7 +274,7 @@ namespace MatFileHandler
throw new HandlerException("Unexpected type in row indices of a sparse array."); throw new HandlerException("Unexpected type in row indices of a sparse array.");
var columnIndex = Read(reader) as MiNum<int> ?? var columnIndex = Read(reader) as MiNum<int> ??
throw new HandlerException("Unexpected type in column indices of a sparse array."); throw new HandlerException("Unexpected type in column indices of a sparse array.");
var data = Read(reader); var data = Read(reader) ?? throw new HandlerException("Missing sparse array data.");
if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsLogical)) if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsLogical))
{ {
return DataElementConverter.ConvertToMatSparseArrayOf<bool>( return DataElementConverter.ConvertToMatSparseArrayOf<bool>(
@ -260,7 +288,7 @@ namespace MatFileHandler
if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsComplex)) if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsComplex))
{ {
var imaginaryData = Read(reader); var imaginaryData = Read(reader) ?? throw new HandlerException("Missing imaginary part of sparse array data.");
return DataElementConverter.ConvertToMatSparseArrayOfComplex( return DataElementConverter.ConvertToMatSparseArrayOfComplex(
sparseArrayFlags, sparseArrayFlags,
dimensions, dimensions,
@ -327,7 +355,7 @@ namespace MatFileHandler
using (var positionTrackingStream = new PositionTrackingStream(bufferedStream)) using (var positionTrackingStream = new PositionTrackingStream(bufferedStream))
using (var innerReader = new BinaryReader(positionTrackingStream)) using (var innerReader = new BinaryReader(positionTrackingStream))
{ {
element = Read(innerReader); element = Read(innerReader) ?? throw new HandlerException("Missing compressed data.");
} }
if (substream.Position != substream.Length) if (substream.Position != substream.Length)
@ -350,7 +378,7 @@ namespace MatFileHandler
return MatArray.Empty(); return MatArray.Empty();
} }
var element1 = Read(reader); var element1 = Read(reader) ?? throw new HandlerException("Missing matrix data.");
var flags = ReadArrayFlags(element1); var flags = ReadArrayFlags(element1);
if (flags.Class == ArrayType.MxOpaque) if (flags.Class == ArrayType.MxOpaque)
{ {
@ -372,12 +400,12 @@ namespace MatFileHandler
return ContinueReadingSparseArray(reader, element1, dimensions, name); return ContinueReadingSparseArray(reader, element1, dimensions, name);
} }
var element4 = Read(reader); var element4 = Read(reader) ?? throw new HandlerException("Missing matrix data.");
var data = ReadData(element4); var data = ReadData(element4);
DataElement? imaginaryData = null; DataElement? imaginaryData = null;
if (flags.Variable.HasFlag(Variable.IsComplex)) if (flags.Variable.HasFlag(Variable.IsComplex))
{ {
var element5 = Read(reader); var element5 = Read(reader) ?? throw new HandlerException("Missing complex matrix data.");
imaginaryData = ReadData(element5); imaginaryData = ReadData(element5);
} }

View File

@ -47,11 +47,14 @@ namespace MatFileHandler
var variables = new List<RawVariable>(); var variables = new List<RawVariable>();
var dataElementReader = new DataElementReader(subsystemData); var dataElementReader = new DataElementReader(subsystemData);
while (true) while (true)
{
try
{ {
var position = reader.BaseStream.Position; var position = reader.BaseStream.Position;
var dataElement = dataElementReader.Read(reader); var dataElement = dataElementReader.Read(reader);
if (dataElement is null)
{
break;
}
if (position == subsystemDataOffset) if (position == subsystemDataOffset)
{ {
var subsystemDataElement = dataElement as IArrayOf<byte> var subsystemDataElement = dataElement as IArrayOf<byte>
@ -64,11 +67,6 @@ namespace MatFileHandler
variables.Add(new RawVariable(position, dataElement)); variables.Add(new RawVariable(position, dataElement));
} }
} }
catch (EndOfStreamException)
{
break;
}
}
return variables; return variables;
} }