Use C# 8.0 and enable nullable reference types #10
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
@ -33,8 +33,8 @@ namespace MatFileHandler
|
|||||||
DataElement data,
|
DataElement data,
|
||||||
DataElement imaginaryData)
|
DataElement imaginaryData)
|
||||||
{
|
{
|
||||||
var realParts = DataExtraction.GetDataAsDouble(data).ToArrayLazily();
|
var realParts = DataExtraction.GetDataAsDouble(data);
|
||||||
var imaginaryParts = DataExtraction.GetDataAsDouble(imaginaryData).ToArrayLazily();
|
var imaginaryParts = DataExtraction.GetDataAsDouble(imaginaryData);
|
||||||
if (realParts == null)
|
if (realParts == null)
|
||||||
{
|
{
|
||||||
throw new HandlerException("Couldn't read sparse array.");
|
throw new HandlerException("Couldn't read sparse array.");
|
||||||
@ -106,12 +106,12 @@ namespace MatFileHandler
|
|||||||
int[] dimensions,
|
int[] dimensions,
|
||||||
string name,
|
string name,
|
||||||
DataElement realData,
|
DataElement realData,
|
||||||
DataElement imaginaryData)
|
DataElement? imaginaryData)
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
if (flags.Variable.HasFlag(Variable.IsLogical))
|
if (flags.Variable.HasFlag(Variable.IsLogical))
|
||||||
{
|
{
|
||||||
var data = DataExtraction.GetDataAsUInt8(realData).ToArrayLazily().Select(x => x != 0).ToArray();
|
var data = DataExtraction.GetDataAsUInt8(realData).Select(x => x != 0).ToArray();
|
||||||
return new MatNumericalArrayOf<bool>(flags, dimensions, name, data);
|
return new MatNumericalArrayOf<bool>(flags, dimensions, name, data);
|
||||||
}
|
}
|
||||||
switch (flags.Class)
|
switch (flags.Class)
|
||||||
@ -139,6 +139,11 @@ namespace MatFileHandler
|
|||||||
var dataArray = ConvertDataToProperType<T>(realData, flags.Class);
|
var dataArray = ConvertDataToProperType<T>(realData, flags.Class);
|
||||||
if (flags.Variable.HasFlag(Variable.IsComplex))
|
if (flags.Variable.HasFlag(Variable.IsComplex))
|
||||||
{
|
{
|
||||||
|
if (imaginaryData is null)
|
||||||
|
{
|
||||||
|
throw new HandlerException("Imaginary part of a complex variable not found.");
|
||||||
|
}
|
||||||
|
|
||||||
var dataArray2 = ConvertDataToProperType<T>(imaginaryData, flags.Class);
|
var dataArray2 = ConvertDataToProperType<T>(imaginaryData, flags.Class);
|
||||||
if (flags.Class == ArrayType.MxDouble)
|
if (flags.Class == ArrayType.MxDouble)
|
||||||
{
|
{
|
||||||
@ -163,49 +168,26 @@ namespace MatFileHandler
|
|||||||
string name,
|
string name,
|
||||||
MiNum<byte> dataElement)
|
MiNum<byte> dataElement)
|
||||||
{
|
{
|
||||||
var data = dataElement?.Data;
|
var data = dataElement.Data;
|
||||||
return new MatCharArrayOf<byte>(flags, dimensions, name, data, Encoding.UTF8.GetString(data));
|
return new MatCharArrayOf<byte>(flags, dimensions, name, data, Encoding.UTF8.GetString(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T[] ConvertDataToProperType<T>(DataElement data, ArrayType arrayType)
|
private static T[] ConvertDataToProperType<T>(DataElement data, ArrayType arrayType)
|
||||||
{
|
{
|
||||||
switch (arrayType)
|
return TryConvertDataToProperType<T>(data, arrayType)
|
||||||
{
|
?? throw new HandlerException($"Unexpected data type.");
|
||||||
case ArrayType.MxDouble:
|
|
||||||
return DataExtraction.GetDataAsDouble(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxSingle:
|
|
||||||
return DataExtraction.GetDataAsSingle(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxInt8:
|
|
||||||
return DataExtraction.GetDataAsInt8(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxUInt8:
|
|
||||||
return DataExtraction.GetDataAsUInt8(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxInt16:
|
|
||||||
return DataExtraction.GetDataAsInt16(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxUInt16:
|
|
||||||
return DataExtraction.GetDataAsUInt16(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxInt32:
|
|
||||||
return DataExtraction.GetDataAsInt32(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxUInt32:
|
|
||||||
return DataExtraction.GetDataAsUInt32(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxInt64:
|
|
||||||
return DataExtraction.GetDataAsInt64(data).ToArrayLazily() as T[];
|
|
||||||
case ArrayType.MxUInt64:
|
|
||||||
return DataExtraction.GetDataAsUInt64(data).ToArrayLazily() as T[];
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T[] ConvertDataToSparseProperType<T>(DataElement data, bool isLogical)
|
private static T[]? ConvertDataToSparseProperType<T>(DataElement data, bool isLogical)
|
||||||
{
|
{
|
||||||
if (isLogical)
|
if (isLogical)
|
||||||
{
|
{
|
||||||
return DataExtraction.GetDataAsUInt8(data).ToArrayLazily().Select(x => x != 0).ToArray() as T[];
|
return DataExtraction.GetDataAsUInt8(data).Select(x => x != 0).ToArray() as T[];
|
||||||
}
|
}
|
||||||
switch (data)
|
switch (data)
|
||||||
{
|
{
|
||||||
case MiNum<double> _:
|
case MiNum<double> _:
|
||||||
return DataExtraction.GetDataAsDouble(data).ToArrayLazily() as T[];
|
return DataExtraction.GetDataAsDouble(data) as T[];
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
@ -217,7 +199,7 @@ namespace MatFileHandler
|
|||||||
string name,
|
string name,
|
||||||
MiNum<ushort> dataElement)
|
MiNum<ushort> dataElement)
|
||||||
{
|
{
|
||||||
var data = dataElement?.Data;
|
var data = dataElement.Data;
|
||||||
return new MatCharArrayOf<ushort>(
|
return new MatCharArrayOf<ushort>(
|
||||||
flags,
|
flags,
|
||||||
dimensions,
|
dimensions,
|
||||||
@ -226,7 +208,7 @@ namespace MatFileHandler
|
|||||||
new string(data.Select(x => (char)x).ToArray()));
|
new string(data.Select(x => (char)x).ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<(int, int), T> ConvertMatlabSparseToDictionary<T>(
|
private static Dictionary<(int row, int column), T> ConvertMatlabSparseToDictionary<T>(
|
||||||
int[] rowIndex,
|
int[] rowIndex,
|
||||||
int[] columnIndex,
|
int[] columnIndex,
|
||||||
Func<int, T> get)
|
Func<int, T> get)
|
||||||
@ -242,5 +224,23 @@ namespace MatFileHandler
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static T[]? TryConvertDataToProperType<T>(DataElement data, ArrayType arrayType)
|
||||||
|
{
|
||||||
|
return arrayType switch
|
||||||
|
{
|
||||||
|
ArrayType.MxDouble => DataExtraction.GetDataAsDouble(data) as T[],
|
||||||
|
ArrayType.MxSingle => DataExtraction.GetDataAsSingle(data) as T[],
|
||||||
|
ArrayType.MxInt8 => DataExtraction.GetDataAsInt8(data) as T[],
|
||||||
|
ArrayType.MxUInt8 => DataExtraction.GetDataAsUInt8(data) as T[],
|
||||||
|
ArrayType.MxInt16 => DataExtraction.GetDataAsInt16(data) as T[],
|
||||||
|
ArrayType.MxUInt16 => DataExtraction.GetDataAsUInt16(data) as T[],
|
||||||
|
ArrayType.MxInt32 => DataExtraction.GetDataAsInt32(data) as T[],
|
||||||
|
ArrayType.MxUInt32 => DataExtraction.GetDataAsUInt32(data) as T[],
|
||||||
|
ArrayType.MxInt64 => DataExtraction.GetDataAsInt64(data) as T[],
|
||||||
|
ArrayType.MxUInt64 => DataExtraction.GetDataAsUInt64(data) as T[],
|
||||||
|
_ => throw new NotSupportedException()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -194,7 +194,7 @@ namespace MatFileHandler
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (BinaryReader, Tag) ReadTag(BinaryReader reader)
|
private static (BinaryReader reader, Tag tag) ReadTag(BinaryReader reader)
|
||||||
{
|
{
|
||||||
var type = reader.ReadInt32();
|
var type = reader.ReadInt32();
|
||||||
var typeHi = type >> 16;
|
var typeHi = type >> 16;
|
||||||
@ -222,7 +222,8 @@ namespace MatFileHandler
|
|||||||
var elements = new List<IArray>();
|
var elements = new List<IArray>();
|
||||||
for (var i = 0; i < numberOfElements; i++)
|
for (var i = 0; i < numberOfElements; i++)
|
||||||
{
|
{
|
||||||
var element = Read(reader) as IArray;
|
var element = Read(reader) as IArray
|
||||||
|
?? throw new HandlerException("Unable to read cell array.");
|
||||||
elements.Add(element);
|
elements.Add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,8 +320,9 @@ namespace MatFileHandler
|
|||||||
string name,
|
string name,
|
||||||
int fieldNameLength)
|
int fieldNameLength)
|
||||||
{
|
{
|
||||||
var element = Read(reader);
|
var element = Read(reader) as MiNum<sbyte>
|
||||||
var fieldNames = ReadFieldNames(element as MiNum<sbyte>, fieldNameLength);
|
?? throw new HandlerException("Unable to parse structure field names.");
|
||||||
|
var fieldNames = ReadFieldNames(element, fieldNameLength);
|
||||||
var fields = new Dictionary<string, List<IArray>>();
|
var fields = new Dictionary<string, List<IArray>>();
|
||||||
foreach (var fieldName in fieldNames)
|
foreach (var fieldName in fieldNames)
|
||||||
{
|
{
|
||||||
@ -332,7 +334,8 @@ namespace MatFileHandler
|
|||||||
{
|
{
|
||||||
foreach (var fieldName in fieldNames)
|
foreach (var fieldName in fieldNames)
|
||||||
{
|
{
|
||||||
var field = Read(reader) as IArray;
|
var field = Read(reader) as IArray
|
||||||
|
?? throw new HandlerException("Unable to parse field name.");
|
||||||
fields[fieldName].Add(field);
|
fields[fieldName].Add(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,7 +401,7 @@ namespace MatFileHandler
|
|||||||
|
|
||||||
var element4 = Read(reader);
|
var element4 = Read(reader);
|
||||||
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);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,20 +30,24 @@ namespace MatFileHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||||
var dataArray = matObject["data", 0] as IArrayOf<double>;
|
|
||||||
if (dataArray is null)
|
switch (matObject["data", 0])
|
||||||
{
|
{
|
||||||
var dataComplex = matObject["data", 0] as IArrayOf<Complex>;
|
case IArrayOf<double> dataArray:
|
||||||
var complexData = dataComplex.ConvertToComplexArray();
|
data = dataArray.ConvertToDoubleArray()
|
||||||
|
?? throw new HandlerException("Cannot extract data for the datetime adapter.");
|
||||||
|
data2 = new double[data.Length];
|
||||||
|
dimensions = dataArray.Dimensions;
|
||||||
|
break;
|
||||||
|
case IArrayOf<Complex> dataComplex:
|
||||||
|
var complexData = dataComplex.ConvertToComplexArray()
|
||||||
|
?? throw new HandlerException("Cannot extract data for the datetime adapter.");
|
||||||
data = complexData.Select(c => c.Real).ToArray();
|
data = complexData.Select(c => c.Real).ToArray();
|
||||||
data2 = complexData.Select(c => c.Imaginary).ToArray();
|
data2 = complexData.Select(c => c.Imaginary).ToArray();
|
||||||
dimensions = dataComplex.Dimensions;
|
dimensions = dataComplex.Dimensions;
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
throw new HandlerException("Datetime data not found.");
|
||||||
data = dataArray.ConvertToDoubleArray();
|
|
||||||
data2 = new double[data.Length];
|
|
||||||
dimensions = dataArray.Dimensions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ namespace MatFileHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dataObject = matObject["millis", 0];
|
var dataObject = matObject["millis", 0];
|
||||||
data = dataObject.ConvertToDoubleArray();
|
data = dataObject.ConvertToDoubleArray()
|
||||||
|
?? throw new HandlerException("Cannot extract data for the duration adapter.");
|
||||||
dimensions = dataObject.Dimensions;
|
dimensions = dataObject.Dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ using System;
|
|||||||
namespace MatFileHandler
|
namespace MatFileHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exception related to Matlab data handling
|
/// Exception related to Matlab data handling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HandlerException : Exception
|
public class HandlerException : Exception
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@ namespace MatFileHandler
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">Error message.</param>
|
/// <param name="message">Error message.</param>
|
||||||
/// <param name="innerException">Inner exception.</param>
|
/// <param name="innerException">Inner exception.</param>
|
||||||
public HandlerException(string message, Exception innerException = null)
|
public HandlerException(string message, Exception? innerException = null)
|
||||||
: base(message, innerException)
|
: base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ namespace MatFileHandler
|
|||||||
/// Tries to convert the array to an array of Double values.
|
/// Tries to convert the array to an array of Double values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
||||||
double[] ConvertToDoubleArray();
|
double[]? ConvertToDoubleArray();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to convert the array to an array of Complex values.
|
/// Tries to convert the array to an array of Complex values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
||||||
Complex[] ConvertToComplexArray();
|
Complex[]? ConvertToComplexArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace MatFileHandler
|
|||||||
/// * for cell arrays:
|
/// * for cell arrays:
|
||||||
/// IArray;
|
/// IArray;
|
||||||
/// * for structure arrays:
|
/// * for structure arrays:
|
||||||
/// IReadOnlyDictionary<string, IArray>;
|
/// IReadOnlyDictionary<string, IArray>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public interface IArrayOf<T> : IArray
|
public interface IArrayOf<T> : IArray
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,6 @@ namespace MatFileHandler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a dictionary mapping indices to values.
|
/// Gets a dictionary mapping indices to values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
new IReadOnlyDictionary<(int, int), T> Data { get; }
|
new IReadOnlyDictionary<(int row, int column), T> Data { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -54,13 +54,13 @@ namespace MatFileHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual double[] ConvertToDoubleArray()
|
public virtual double[]? ConvertToDoubleArray()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Complex[] ConvertToComplexArray()
|
public virtual Complex[]? ConvertToComplexArray()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<DocumentationFile>$(OutputPath)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>$(OutputPath)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<LangVersion>8.0</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<CodeAnalysisRuleSet>..\MatFileHandler.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>..\MatFileHandler.ruleset</CodeAnalysisRuleSet>
|
||||||
@ -26,7 +28,7 @@
|
|||||||
<AdditionalFiles Include="..\stylecop.json" />
|
<AdditionalFiles Include="..\stylecop.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta004">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||||
<PrivateAssets>All</PrivateAssets>
|
<PrivateAssets>All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.4.0" Condition="'$(TargetFramework)' == 'net461'" />
|
<PackageReference Include="System.ValueTuple" Version="4.4.0" Condition="'$(TargetFramework)' == 'net461'" />
|
||||||
|
@ -57,7 +57,8 @@ namespace MatFileHandler
|
|||||||
var dataElement = dataElementReader.Read(reader);
|
var dataElement = dataElementReader.Read(reader);
|
||||||
if (position == subsystemDataOffset)
|
if (position == subsystemDataOffset)
|
||||||
{
|
{
|
||||||
var subsystemDataElement = dataElement as IArrayOf<byte>;
|
var subsystemDataElement = dataElement as IArrayOf<byte>
|
||||||
|
?? throw new HandlerException("Cannot parse subsystem data element.");
|
||||||
var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData);
|
var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData);
|
||||||
subsystemData.Set(newSubsystemData);
|
subsystemData.Set(newSubsystemData);
|
||||||
}
|
}
|
||||||
|
@ -198,14 +198,14 @@ namespace MatFileHandler
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private (byte[], byte[]) ConvertToPairOfByteArrays<T>(ComplexOf<T>[] data)
|
private (byte[] real, byte[] imaginary) ConvertToPairOfByteArrays<T>(ComplexOf<T>[] data)
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
return (ConvertToByteArray(data.Select(x => x.Real).ToArray()),
|
return (ConvertToByteArray(data.Select(x => x.Real).ToArray()),
|
||||||
ConvertToByteArray(data.Select(x => x.Imaginary).ToArray()));
|
ConvertToByteArray(data.Select(x => x.Imaginary).ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private (byte[], byte[]) ConvertToPairOfByteArrays(Complex[] data)
|
private (byte[] real, byte[] imaginary) ConvertToPairOfByteArrays(Complex[] data)
|
||||||
{
|
{
|
||||||
return (ConvertToByteArray(data.Select(x => x.Real).ToArray()),
|
return (ConvertToByteArray(data.Select(x => x.Real).ToArray()),
|
||||||
ConvertToByteArray(data.Select(x => x.Imaginary).ToArray()));
|
ConvertToByteArray(data.Select(x => x.Imaginary).ToArray()));
|
||||||
@ -496,8 +496,8 @@ namespace MatFileHandler
|
|||||||
for (var column = 0; column < numberOfColumns; column++)
|
for (var column = 0; column < numberOfColumns; column++)
|
||||||
{
|
{
|
||||||
var column1 = column;
|
var column1 = column;
|
||||||
var thisColumn = keys.Where(pair => pair.Item2 == column1 && !dict[pair].Equals(default(T)));
|
var thisColumn = keys.Where(pair => pair.column == column1 && !dict[pair].Equals(default));
|
||||||
var thisRow = thisColumn.Select(pair => pair.Item1).OrderBy(x => x).ToArray();
|
var thisRow = thisColumn.Select(pair => pair.row).OrderBy(x => x).ToArray();
|
||||||
rowIndexList.AddRange(thisRow);
|
rowIndexList.AddRange(thisRow);
|
||||||
valuesList.AddRange(thisRow.Select(row => dict[(row, column1)]));
|
valuesList.AddRange(thisRow.Select(row => dict[(row, column1)]));
|
||||||
columnIndex[column + 1] = rowIndexList.Count;
|
columnIndex[column + 1] = rowIndexList.Count;
|
||||||
|
@ -43,58 +43,152 @@ namespace MatFileHandler
|
|||||||
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
/// <returns>Array of values of the array, converted to Double, or null if the conversion is not possible.</returns>
|
||||||
public override double[] ConvertToDoubleArray()
|
public override double[] ConvertToDoubleArray()
|
||||||
{
|
{
|
||||||
return Data as double[] ?? Data.Select(x => Convert.ToDouble(x)).ToArray();
|
return Data switch
|
||||||
|
{
|
||||||
|
sbyte[] sbyteData => DataExtraction.SbyteToDouble(sbyteData),
|
||||||
|
byte[] byteData => DataExtraction.ByteToDouble(byteData),
|
||||||
|
short[] shortData => DataExtraction.ShortToDouble(shortData),
|
||||||
|
ushort[] ushortData => DataExtraction.UshortToDouble(ushortData),
|
||||||
|
int[] intData => DataExtraction.IntToDouble(intData),
|
||||||
|
uint[] uintData => DataExtraction.UintToDouble(uintData),
|
||||||
|
long[] longData => DataExtraction.LongToDouble(longData),
|
||||||
|
ulong[] ulongData => DataExtraction.UlongToDouble(ulongData),
|
||||||
|
float[] floatData => DataExtraction.FloatToDouble(floatData),
|
||||||
|
double[] doubleData => doubleData,
|
||||||
|
_ => throw new HandlerException("Cannot convert data to double array.")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to convert the array to an array of Complex values.
|
/// Tries to convert the array to an array of Complex values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
/// <returns>Array of values of the array, converted to Complex, or null if the conversion is not possible.</returns>
|
||||||
public override Complex[] ConvertToComplexArray()
|
public override Complex[]? ConvertToComplexArray()
|
||||||
{
|
{
|
||||||
if (Data is Complex[])
|
return Data switch
|
||||||
{
|
{
|
||||||
return Data as Complex[];
|
Complex[] data => data,
|
||||||
}
|
ComplexOf<sbyte>[] ofs => ConvertToComplex(ofs),
|
||||||
if (Data is ComplexOf<sbyte>[])
|
ComplexOf<byte>[] ofs => ConvertToComplex(ofs),
|
||||||
{
|
ComplexOf<short>[] ofs => ConvertToComplex(ofs),
|
||||||
return ConvertToComplex(Data as ComplexOf<sbyte>[]);
|
ComplexOf<ushort>[] ofs => ConvertToComplex(ofs),
|
||||||
}
|
ComplexOf<int>[] ofs => ConvertToComplex(ofs),
|
||||||
if (Data is ComplexOf<byte>[])
|
ComplexOf<uint>[] ofs => ConvertToComplex(ofs),
|
||||||
{
|
ComplexOf<long>[] ofs => ConvertToComplex(ofs),
|
||||||
return ConvertToComplex(Data as ComplexOf<byte>[]);
|
ComplexOf<ulong>[] ofs => ConvertToComplex(ofs),
|
||||||
}
|
ComplexOf<float>[] ofs => ConvertToComplex(ofs),
|
||||||
if (Data is ComplexOf<short>[])
|
_ => ConvertToComplex(ConvertToDoubleArray())
|
||||||
{
|
};
|
||||||
return ConvertToComplex(Data as ComplexOf<short>[]);
|
|
||||||
}
|
|
||||||
if (Data is ComplexOf<ushort>[])
|
|
||||||
{
|
|
||||||
return ConvertToComplex(Data as ComplexOf<ushort>[]);
|
|
||||||
}
|
|
||||||
if (Data is ComplexOf<int>[])
|
|
||||||
{
|
|
||||||
return ConvertToComplex(Data as ComplexOf<int>[]);
|
|
||||||
}
|
|
||||||
if (Data is ComplexOf<uint>[])
|
|
||||||
{
|
|
||||||
return ConvertToComplex(Data as ComplexOf<uint>[]);
|
|
||||||
}
|
|
||||||
if (Data is ComplexOf<long>[])
|
|
||||||
{
|
|
||||||
return ConvertToComplex(Data as ComplexOf<long>[]);
|
|
||||||
}
|
|
||||||
if (Data is ComplexOf<ulong>[])
|
|
||||||
{
|
|
||||||
return ConvertToComplex(Data as ComplexOf<ulong>[]);
|
|
||||||
}
|
|
||||||
return ConvertToDoubleArray().Select(x => new Complex(x, 0.0)).ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Complex[] ConvertToComplex<TS>(IEnumerable<ComplexOf<TS>> array)
|
private static Complex[] ConvertToComplex(ComplexOf<sbyte>[] array)
|
||||||
where TS : struct
|
|
||||||
{
|
{
|
||||||
return array.Select(x => new Complex(Convert.ToDouble(x.Real), Convert.ToDouble(x.Imaginary))).ToArray();
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<byte>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<short>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<ushort>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<int>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<uint>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<long>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<ulong>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(ComplexOf<float>[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(Convert.ToDouble(array[i].Real), Convert.ToDouble(array[i].Imaginary));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Complex[] ConvertToComplex(double[] array)
|
||||||
|
{
|
||||||
|
var result = new Complex[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = new Complex(array[i], 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ namespace MatFileHandler
|
|||||||
SparseArrayFlags flags,
|
SparseArrayFlags flags,
|
||||||
int[] dimensions,
|
int[] dimensions,
|
||||||
string name,
|
string name,
|
||||||
Dictionary<(int, int), T> data)
|
Dictionary<(int row, int column), T> data)
|
||||||
: base(flags.ArrayFlags, dimensions, name)
|
: base(flags.ArrayFlags, dimensions, name)
|
||||||
{
|
{
|
||||||
DataDictionary = data;
|
DataDictionary = data;
|
||||||
@ -39,9 +39,9 @@ namespace MatFileHandler
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyDictionary<(int, int), T> Data => DataDictionary;
|
public IReadOnlyDictionary<(int row, int column), T> Data => DataDictionary;
|
||||||
|
|
||||||
private Dictionary<(int, int), T> DataDictionary { get; }
|
private Dictionary<(int row, int column), T> DataDictionary { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public T this[params int[] list]
|
public T this[params int[] list]
|
||||||
|
@ -35,7 +35,19 @@ namespace MatFileHandler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets null: not implemented.
|
/// Gets null: not implemented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyDictionary<string, IArray>[] Data => null;
|
public IReadOnlyDictionary<string, IArray>[] Data
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new IReadOnlyDictionary<string, IArray>[Count];
|
||||||
|
for (var i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
result[i] = FieldNames.ToDictionary(name => name, name => Fields[name][i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a dictionary that maps field names to lists of values.
|
/// Gets a dictionary that maps field names to lists of values.
|
||||||
@ -128,7 +140,7 @@ namespace MatFileHandler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the structure has a given field.
|
/// Checks if the structure has a given field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Field name</param>
|
/// <param name="key">Field name.</param>
|
||||||
/// <returns>True iff the structure has a given field.</returns>
|
/// <returns>True iff the structure has a given field.</returns>
|
||||||
public bool ContainsKey(string key) => Parent.Fields.ContainsKey(key);
|
public bool ContainsKey(string key) => Parent.Fields.ContainsKey(key);
|
||||||
|
|
||||||
@ -138,12 +150,14 @@ namespace MatFileHandler
|
|||||||
/// <param name="key">Field name.</param>
|
/// <param name="key">Field name.</param>
|
||||||
/// <param name="value">Value (or null if the field is not present).</param>
|
/// <param name="value">Value (or null if the field is not present).</param>
|
||||||
/// <returns>Success status of the query.</returns>
|
/// <returns>Success status of the query.</returns>
|
||||||
public bool TryGetValue(string key, out IArray value)
|
#pragma warning disable CS8614
|
||||||
|
public bool TryGetValue(string key, out IArray? value)
|
||||||
|
#pragma warning restore CS8614
|
||||||
{
|
{
|
||||||
var success = Parent.Fields.TryGetValue(key, out var array);
|
var success = Parent.Fields.TryGetValue(key, out var array);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
value = default(IArray);
|
value = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
value = array[Index];
|
value = array[Index];
|
||||||
|
@ -50,9 +50,9 @@ namespace MatFileHandler
|
|||||||
public string TypeDescription { get; }
|
public string TypeDescription { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Complex[] ConvertToComplexArray() => null;
|
public override Complex[]? ConvertToComplexArray() => null;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override double[] ConvertToDoubleArray() => null;
|
public override double[]? ConvertToDoubleArray() => null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -47,7 +47,21 @@ namespace MatFileHandler
|
|||||||
public int ClassIndex { get; }
|
public int ClassIndex { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyDictionary<string, IArray>[] Data => null;
|
public IReadOnlyDictionary<string, IArray>[] Data
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new IReadOnlyDictionary<string, IArray>[Count];
|
||||||
|
for (var i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
result[i] = FieldNamesArray.ToDictionary(
|
||||||
|
name => name,
|
||||||
|
name => this[name, i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<string> FieldNames => FieldNamesArray;
|
public IEnumerable<string> FieldNames => FieldNamesArray;
|
||||||
@ -71,7 +85,7 @@ namespace MatFileHandler
|
|||||||
{
|
{
|
||||||
if (TryGetValue(field, out var result, list))
|
if (TryGetValue(field, out var result, list))
|
||||||
{
|
{
|
||||||
return result;
|
return result!;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IndexOutOfRangeException();
|
throw new IndexOutOfRangeException();
|
||||||
@ -91,19 +105,19 @@ namespace MatFileHandler
|
|||||||
return new OpaqueObjectArrayElement(this, i);
|
return new OpaqueObjectArrayElement(this, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetValue(string field, out IArray output, params int[] list)
|
private bool TryGetValue(string field, out IArray? output, params int[] list)
|
||||||
{
|
{
|
||||||
var index = Dimensions.DimFlatten(list);
|
var index = Dimensions.DimFlatten(list);
|
||||||
var maybeFieldIndex = subsystemData.ClassInformation[ClassIndex].FindField(field);
|
var maybeFieldIndex = subsystemData.ClassInformation[ClassIndex].FindField(field);
|
||||||
if (!(maybeFieldIndex is int fieldIndex))
|
if (!(maybeFieldIndex is int fieldIndex))
|
||||||
{
|
{
|
||||||
output = default(IArray);
|
output = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index >= IndexToObjectId.Length)
|
if (index >= IndexToObjectId.Length)
|
||||||
{
|
{
|
||||||
output = default(IArray);
|
output = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +175,9 @@ namespace MatFileHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool TryGetValue(string key, out IArray value)
|
#pragma warning disable CS8614
|
||||||
|
public bool TryGetValue(string key, out IArray? value)
|
||||||
|
#pragma warning restore CS8614
|
||||||
{
|
{
|
||||||
return parent.TryGetValue(key, out value, index);
|
return parent.TryGetValue(key, out value, index);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ namespace MatFileHandler
|
|||||||
throw new ArgumentException("The object provided is not a string.");
|
throw new ArgumentException("The object provided is not a string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var binaryData = matObject["any", 0] as IArrayOf<ulong>;
|
var binaryData = matObject["any", 0] as IArrayOf<ulong>
|
||||||
|
?? throw new HandlerException("Cannot extract string data.");
|
||||||
|
|
||||||
(dimensions, strings) = ParseBinaryData(binaryData.Data);
|
(dimensions, strings) = ParseBinaryData(binaryData.Data);
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,15 @@ namespace MatFileHandler
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class SubsystemData
|
internal class SubsystemData
|
||||||
{
|
{
|
||||||
|
private RealSubsystemData? _realData;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SubsystemData"/> class.
|
/// Initializes a new instance of the <see cref="SubsystemData"/> class.
|
||||||
/// Default constructor: initializes everything to null.
|
/// Default constructor: initializes everything to null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SubsystemData()
|
public SubsystemData()
|
||||||
{
|
{
|
||||||
ClassInformation = null;
|
_realData = null;
|
||||||
ObjectInformation = null;
|
|
||||||
Data = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -35,27 +35,29 @@ namespace MatFileHandler
|
|||||||
Dictionary<int, ObjectInfo> objectInformation,
|
Dictionary<int, ObjectInfo> objectInformation,
|
||||||
Dictionary<int, IArray> data)
|
Dictionary<int, IArray> data)
|
||||||
{
|
{
|
||||||
this.ClassInformation =
|
_realData = new RealSubsystemData(
|
||||||
classInformation ?? throw new ArgumentNullException(nameof(classInformation));
|
classInformation,
|
||||||
this.ObjectInformation =
|
objectInformation,
|
||||||
objectInformation ?? throw new ArgumentNullException(nameof(objectInformation));
|
data);
|
||||||
this.Data = data ?? throw new ArgumentNullException(nameof(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets information about all the classes occurring in the file.
|
/// Gets information about all the classes occurring in the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<int, ClassInfo> ClassInformation { get; set; }
|
public Dictionary<int, ClassInfo> ClassInformation =>
|
||||||
|
_realData?.ClassInformation ?? throw new HandlerException("Subsystem data missing.");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the actual data: mapping of "object field" indices to their values.
|
/// Gets the actual data: mapping of "object field" indices to their values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyDictionary<int, IArray> Data { get; set; }
|
public IReadOnlyDictionary<int, IArray> Data =>
|
||||||
|
_realData?.Data ?? throw new HandlerException("Subsystem data missing.");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets information about all the objects occurring in the file.
|
/// Gets information about all the objects occurring in the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<int, ObjectInfo> ObjectInformation { get; set; }
|
public Dictionary<int, ObjectInfo> ObjectInformation =>
|
||||||
|
_realData?.ObjectInformation ?? throw new HandlerException("Subsystem data missing.");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize this object from another object.
|
/// Initialize this object from another object.
|
||||||
@ -66,9 +68,10 @@ namespace MatFileHandler
|
|||||||
/// <param name="data">Another subsystem data.</param>
|
/// <param name="data">Another subsystem data.</param>
|
||||||
public void Set(SubsystemData data)
|
public void Set(SubsystemData data)
|
||||||
{
|
{
|
||||||
this.ClassInformation = data.ClassInformation;
|
_realData = new RealSubsystemData(
|
||||||
this.ObjectInformation = data.ObjectInformation;
|
data.ClassInformation,
|
||||||
this.Data = data.Data;
|
data.ObjectInformation,
|
||||||
|
data.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -136,5 +139,39 @@ namespace MatFileHandler
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyDictionary<int, int> FieldLinks => fieldLinks;
|
public IReadOnlyDictionary<int, int> FieldLinks => fieldLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RealSubsystemData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RealSubsystemData"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="classInformation">Class information.</param>
|
||||||
|
/// <param name="objectInformation">Object information.</param>
|
||||||
|
/// <param name="data">Data.</param>
|
||||||
|
public RealSubsystemData(
|
||||||
|
Dictionary<int, ClassInfo> classInformation,
|
||||||
|
Dictionary<int, ObjectInfo> objectInformation,
|
||||||
|
IReadOnlyDictionary<int, IArray> data)
|
||||||
|
{
|
||||||
|
ClassInformation = classInformation ?? throw new ArgumentNullException(nameof(classInformation));
|
||||||
|
ObjectInformation = objectInformation ?? throw new ArgumentNullException(nameof(objectInformation));
|
||||||
|
Data = data ?? throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets information about all the classes occurring in the file.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<int, ClassInfo> ClassInformation { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the actual data: mapping of "object field" indices to their values.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyDictionary<int, IArray> Data { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets information about all the objects occurring in the file.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<int, ObjectInfo> ObjectInformation { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,65 +23,27 @@ namespace MatFileHandler
|
|||||||
/// <returns>Subsystem data read.</returns>
|
/// <returns>Subsystem data read.</returns>
|
||||||
public static SubsystemData Read(byte[] bytes, SubsystemData subsystemData)
|
public static SubsystemData Read(byte[] bytes, SubsystemData subsystemData)
|
||||||
{
|
{
|
||||||
List<RawVariable> rawVariables = null;
|
var rawVariables = ReadRawVariables(bytes, subsystemData);
|
||||||
using (var stream = new MemoryStream(bytes))
|
|
||||||
{
|
|
||||||
using (var reader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
reader.ReadBytes(8);
|
|
||||||
rawVariables = MatFileReader.ReadRawVariables(reader, -1, subsystemData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse subsystem data.
|
// Parse subsystem data.
|
||||||
var mainVariable = rawVariables[0].DataElement as IStructureArray;
|
var mainVariable = rawVariables[0].DataElement as IStructureArray
|
||||||
var mcosData = mainVariable["MCOS", 0] as Opaque;
|
?? throw new HandlerException("Subsystem data must be a structure array.");
|
||||||
var opaqueData = mcosData.RawData as ICellArray;
|
var mcosData = mainVariable["MCOS", 0] as Opaque
|
||||||
var info = (opaqueData[0] as IArrayOf<byte>).Data;
|
?? throw new HandlerException("MCOS data must be an opaque object.");
|
||||||
|
var opaqueData = mcosData.RawData as ICellArray
|
||||||
|
?? throw new HandlerException("Opaque data must be a cell array.");
|
||||||
|
var info = (opaqueData[0] as IArrayOf<byte>)?.Data
|
||||||
|
?? throw new HandlerException("Opaque data info must be a byte array.");
|
||||||
var (offsets, position) = ReadOffsets(info, 0);
|
var (offsets, position) = ReadOffsets(info, 0);
|
||||||
var fieldNames = ReadFieldNames(info, position, offsets[1]);
|
var fieldNames = ReadFieldNames(info, position, offsets[1]);
|
||||||
var numberOfClasses = ((offsets[3] - offsets[2]) / 16) - 1;
|
var numberOfClasses = ((offsets[3] - offsets[2]) / 16) - 1;
|
||||||
Dictionary<int, string> classIdToName = null;
|
var classIdToName = ReadClassIdToName(info, offsets, fieldNames, numberOfClasses);
|
||||||
using (var stream = new MemoryStream(info, offsets[2], offsets[3] - offsets[2]))
|
|
||||||
{
|
|
||||||
using (var reader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
classIdToName = ReadClassNames(reader, fieldNames, numberOfClasses);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var numberOfEmbeddedObjects = (offsets[4] - offsets[3] - 8) / 16;
|
var numberOfEmbeddedObjects = (offsets[4] - offsets[3] - 8) / 16;
|
||||||
Dictionary<int, Dictionary<int, int>> embeddedObjectPositionsToValues = null;
|
var embeddedObjectPositionsToValues = ReadEmbeddedObjectPositionsToValues(info, offsets, numberOfEmbeddedObjects);
|
||||||
using (var stream = new MemoryStream(info, offsets[3], offsets[4] - offsets[3]))
|
|
||||||
{
|
|
||||||
using (var reader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
embeddedObjectPositionsToValues =
|
|
||||||
ReadEmbeddedObjectPositionsToValuesMapping(reader, numberOfEmbeddedObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var numberOfObjects = ((offsets[5] - offsets[4]) / 24) - 1;
|
var numberOfObjects = ((offsets[5] - offsets[4]) / 24) - 1;
|
||||||
Dictionary<int, ObjectClassInformation> objectClasses = null;
|
var objectClasses = ReadObjectClassInformations(info, offsets, numberOfObjects);
|
||||||
using (var stream = new MemoryStream(info, offsets[4], offsets[5] - offsets[4]))
|
|
||||||
{
|
|
||||||
using (var reader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
objectClasses = ReadObjectClasses(reader, numberOfObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var numberOfObjectPositions = objectClasses.Values.Count(x => x.ObjectPosition != 0);
|
var numberOfObjectPositions = objectClasses.Values.Count(x => x.ObjectPosition != 0);
|
||||||
|
var objectPositionsToValues = ReadObjectPositionsToValues(info, offsets, numberOfObjectPositions);
|
||||||
Dictionary<int, Dictionary<int, int>> objectPositionsToValues = null;
|
|
||||||
using (var stream = new MemoryStream(info, offsets[5], offsets[6] - offsets[5]))
|
|
||||||
{
|
|
||||||
using (var reader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
objectPositionsToValues = ReadObjectPositionsToValuesMapping(reader, numberOfObjectPositions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (classInformation, objectInformation) =
|
var (classInformation, objectInformation) =
|
||||||
GatherClassAndObjectInformation(
|
GatherClassAndObjectInformation(
|
||||||
classIdToName,
|
classIdToName,
|
||||||
@ -89,7 +51,6 @@ namespace MatFileHandler
|
|||||||
objectClasses,
|
objectClasses,
|
||||||
objectPositionsToValues,
|
objectPositionsToValues,
|
||||||
embeddedObjectPositionsToValues);
|
embeddedObjectPositionsToValues);
|
||||||
|
|
||||||
var allFields = objectInformation.Values.SelectMany(obj => obj.FieldLinks.Values);
|
var allFields = objectInformation.Values.SelectMany(obj => obj.FieldLinks.Values);
|
||||||
var data = new Dictionary<int, IArray>();
|
var data = new Dictionary<int, IArray>();
|
||||||
foreach (var i in allFields)
|
foreach (var i in allFields)
|
||||||
@ -100,7 +61,44 @@ namespace MatFileHandler
|
|||||||
return new SubsystemData(classInformation, objectInformation, data);
|
return new SubsystemData(classInformation, objectInformation, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (Dictionary<int, SubsystemData.ClassInfo>, Dictionary<int, SubsystemData.ObjectInfo>)
|
private static Dictionary<int, Dictionary<int, int>> ReadObjectPositionsToValues(byte[] info, int[] offsets, int numberOfObjectPositions)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(info, offsets[5], offsets[6] - offsets[5]);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
return ReadObjectPositionsToValuesMapping(reader, numberOfObjectPositions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<int, ObjectClassInformation> ReadObjectClassInformations(byte[] info, int[] offsets, int numberOfObjects)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(info, offsets[4], offsets[5] - offsets[4]);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
return ReadObjectClasses(reader, numberOfObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<int, Dictionary<int, int>> ReadEmbeddedObjectPositionsToValues(byte[] info, int[] offsets, int numberOfEmbeddedObjects)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(info, offsets[3], offsets[4] - offsets[3]);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
return ReadEmbeddedObjectPositionsToValuesMapping(reader, numberOfEmbeddedObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<int, string> ReadClassIdToName(byte[] info, int[] offsets, string[] fieldNames, int numberOfClasses)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(info, offsets[2], offsets[3] - offsets[2]);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
return ReadClassNames(reader, fieldNames, numberOfClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<RawVariable> ReadRawVariables(byte[] bytes, SubsystemData subsystemData)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(bytes);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
reader.ReadBytes(8);
|
||||||
|
return MatFileReader.ReadRawVariables(reader, -1, subsystemData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (Dictionary<int, SubsystemData.ClassInfo> classInfos,
|
||||||
|
Dictionary<int, SubsystemData.ObjectInfo> objectInfos)
|
||||||
GatherClassAndObjectInformation(
|
GatherClassAndObjectInformation(
|
||||||
Dictionary<int, string> classIdToName,
|
Dictionary<int, string> classIdToName,
|
||||||
string[] fieldNames,
|
string[] fieldNames,
|
||||||
@ -318,7 +316,7 @@ namespace MatFileHandler
|
|||||||
string.Empty,
|
string.Empty,
|
||||||
string.Empty,
|
string.Empty,
|
||||||
dimensions,
|
dimensions,
|
||||||
array as DataElement,
|
uintArray,
|
||||||
indexToObjectId,
|
indexToObjectId,
|
||||||
classIndex,
|
classIndex,
|
||||||
subsystemData);
|
subsystemData);
|
||||||
|
@ -18,25 +18,34 @@ namespace MatFileHandler
|
|||||||
/// <param name="array">Source table object.</param>
|
/// <param name="array">Source table object.</param>
|
||||||
public TableAdapter(IArray array)
|
public TableAdapter(IArray array)
|
||||||
{
|
{
|
||||||
matObject = array as IMatObject;
|
matObject = array as IMatObject
|
||||||
if (matObject?.ClassName != "table")
|
?? throw new HandlerException("Table adapter must be initialized with a MATLAB object.");
|
||||||
|
if (matObject.ClassName != "table")
|
||||||
{
|
{
|
||||||
throw new ArgumentException("The object provided is not a table.");
|
throw new ArgumentException("The object provided is not a table.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var cellArray = matObject["varnames"] as ICellArray;
|
var cellArray = matObject["varnames"] as ICellArray
|
||||||
|
?? throw new HandlerException("Table variable names must be in a cell array.");
|
||||||
VariableNames = Enumerable
|
VariableNames = Enumerable
|
||||||
.Range(0, cellArray.Count)
|
.Range(0, cellArray.Count)
|
||||||
.Select(i => (cellArray[i] as ICharArray).String)
|
.Select(i =>
|
||||||
|
(cellArray[i] as ICharArray ??
|
||||||
|
throw new HandlerException("Variable name must be a char array.")).String)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
NumberOfVariables = VariableNames.Length;
|
NumberOfVariables = VariableNames.Length;
|
||||||
var props = matObject["props"] as IStructureArray;
|
var props = matObject["props"] as IStructureArray
|
||||||
Description = (props["Description"] as ICharArray).String;
|
?? throw new HandlerException("Table properties must be a structure array.");
|
||||||
NumberOfRows = (int)matObject["nrows"].ConvertToDoubleArray()[0];
|
Description = (props["Description"] as ICharArray
|
||||||
var rowNamesArrays = matObject["rownames"] as ICellArray;
|
?? throw new HandlerException("Table description must be a char array.")).String;
|
||||||
|
NumberOfRows = (int)(matObject["nrows"].ConvertToDoubleArray()
|
||||||
|
?? throw new HandlerException("Cannot find number of rows in a table."))[0];
|
||||||
|
var rowNamesArrays = matObject["rownames"] as ICellArray
|
||||||
|
?? throw new HandlerException("Table row names must be a cell array.");
|
||||||
RowNames = Enumerable
|
RowNames = Enumerable
|
||||||
.Range(0, rowNamesArrays.Count)
|
.Range(0, rowNamesArrays.Count)
|
||||||
.Select(i => (cellArray[i] as ICharArray).String)
|
.Select(i => (cellArray[i] as ICharArray
|
||||||
|
?? throw new HandlerException("Each table row name must be a char array.")).String)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +75,7 @@ namespace MatFileHandler
|
|||||||
public string[] VariableNames { get; }
|
public string[] VariableNames { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all the data for a given variable
|
/// Gets all the data for a given variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="variableName">Variable name.</param>
|
/// <param name="variableName">Variable name.</param>
|
||||||
/// <returns>All data associated with the variable.</returns>
|
/// <returns>All data associated with the variable.</returns>
|
||||||
@ -83,7 +92,8 @@ namespace MatFileHandler
|
|||||||
throw new IndexOutOfRangeException($"Variable '{variableName}' not found.");
|
throw new IndexOutOfRangeException($"Variable '{variableName}' not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = matObject["data"] as ICellArray;
|
var data = matObject["data"] as ICellArray
|
||||||
|
?? throw new HandlerException("Table data must be stored in a cell array.");
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,17 @@
|
|||||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
|
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'vs2017-win2016'
|
vmImage: 'windows-latest'
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
buildConfiguration: 'Release'
|
buildConfiguration: 'Release'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- task: UseDotNet@2
|
||||||
|
displayName: 'Use .NET Core SDK 3.x'
|
||||||
|
inputs:
|
||||||
|
version: 3.x
|
||||||
|
|
||||||
- script: dotnet build --configuration $(buildConfiguration)
|
- script: dotnet build --configuration $(buildConfiguration)
|
||||||
displayName: 'dotnet build $(buildConfiguration)'
|
displayName: 'dotnet build $(buildConfiguration)'
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user