parent
d41020c6b8
commit
5a2226629a
@ -10,8 +10,11 @@ namespace MatFileHandler.Tests
|
||||
/// <summary>
|
||||
/// Tests of Matlab array manipulation.
|
||||
/// </summary>
|
||||
public class ArrayHandlingTests : IDisposable
|
||||
public sealed class ArrayHandlingTests : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Setup for array handling tests.
|
||||
/// </summary>
|
||||
public ArrayHandlingTests()
|
||||
{
|
||||
Builder = new DataBuilder();
|
||||
@ -116,8 +119,12 @@ namespace MatFileHandler.Tests
|
||||
Assert.NotNull(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -164,6 +164,23 @@ namespace MatFileHandler.Tests
|
||||
Assert.Null(array.ConvertToComplexArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test reading an enumeration.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestEnum()
|
||||
{
|
||||
var matFile = GetTests("good")["enum"];
|
||||
var days = matFile["days"].Value;
|
||||
var enumeration = new EnumAdapter(days);
|
||||
Assert.Equal(5, enumeration.Values.Count);
|
||||
Assert.Equal("Wednesday", enumeration.ValueNames[enumeration.Values[0]]);
|
||||
Assert.Equal("Saturday", enumeration.ValueNames[enumeration.Values[1]]);
|
||||
Assert.Equal("Monday", enumeration.ValueNames[enumeration.Values[2]]);
|
||||
Assert.Equal("Wednesday", enumeration.ValueNames[enumeration.Values[3]]);
|
||||
Assert.Equal("Saturday", enumeration.ValueNames[enumeration.Values[4]]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test reading a structure array.
|
||||
/// </summary>
|
||||
@ -487,6 +504,9 @@ namespace MatFileHandler.Tests
|
||||
Assert.Null(d0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test 3-dimensional arrays.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Test_3DArrays()
|
||||
{
|
||||
@ -519,6 +539,9 @@ namespace MatFileHandler.Tests
|
||||
Assert.Null(obj.ConvertTo2dDoubleArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test four-dimensional arrays.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Test_4DArrays()
|
||||
{
|
||||
|
BIN
MatFileHandler.Tests/test-data/good/enum.mat
Normal file
BIN
MatFileHandler.Tests/test-data/good/enum.mat
Normal file
Binary file not shown.
@ -258,7 +258,7 @@ namespace MatFileHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Opaque(name, typeDescription, className, new int[] { }, data);
|
||||
return new Opaque(name, typeDescription, className, new int[] { }, data, subsystemData);
|
||||
}
|
||||
}
|
||||
|
||||
|
60
MatFileHandler/EnumAdapter.cs
Normal file
60
MatFileHandler/EnumAdapter.cs
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
namespace MatFileHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// A better interface for using enum adapter.
|
||||
/// </summary>
|
||||
public class EnumAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnumAdapter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="array">Source enum object.</param>
|
||||
public EnumAdapter(IArray array)
|
||||
{
|
||||
var matObject = array as Opaque;
|
||||
if (matObject?.RawData is not IStructureArray rawData)
|
||||
{
|
||||
throw new HandlerException("Cannot extract data for the enum adapter.");
|
||||
}
|
||||
|
||||
if (rawData["ValueNames"] is not IArrayOf<uint> valueNamesData)
|
||||
{
|
||||
throw new HandlerException("Cannot extract data for the enum adapter.");
|
||||
}
|
||||
|
||||
var numberOfNames = valueNamesData.Count;
|
||||
var valueNames = new string[numberOfNames];
|
||||
var names = matObject.SubsystemData.FieldNames;
|
||||
for (var i = 0; i < numberOfNames; i++)
|
||||
{
|
||||
valueNames[i] = names[valueNamesData[i] - 1];
|
||||
}
|
||||
|
||||
if (rawData["ValueIndices"] is not IArrayOf<uint> valueIndices)
|
||||
{
|
||||
throw new HandlerException("Cannot extract data for the enum adapter.");
|
||||
}
|
||||
|
||||
ClassName = matObject.ClassName;
|
||||
ValueNames = valueNames;
|
||||
Values = valueIndices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets name of the enumeration class.
|
||||
/// </summary>
|
||||
public string ClassName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets names of the enumeration values.
|
||||
/// </summary>
|
||||
public string[] ValueNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets indices of values stored in the variable.
|
||||
/// </summary>
|
||||
public IArrayOf<uint> Values { get; }
|
||||
}
|
||||
}
|
@ -26,12 +26,14 @@ namespace MatFileHandler
|
||||
/// <param name="className">Class name.</param>
|
||||
/// <param name="dimensions">Dimensions of the object.</param>
|
||||
/// <param name="rawData">Raw object's data.</param>
|
||||
public Opaque(string name, string typeDescription, string className, int[] dimensions, DataElement rawData)
|
||||
/// <param name="subsystemData">Subsystem data.</param>
|
||||
public Opaque(string name, string typeDescription, string className, int[] dimensions, DataElement rawData, SubsystemData subsystemData)
|
||||
: base(new ArrayFlags(ArrayType.MxOpaque, 0), dimensions, name)
|
||||
{
|
||||
TypeDescription = typeDescription ?? throw new ArgumentNullException(nameof(typeDescription));
|
||||
ClassName = className ?? throw new ArgumentNullException(nameof(className));
|
||||
RawData = rawData ?? throw new ArgumentNullException(nameof(rawData));
|
||||
SubsystemData = subsystemData ?? throw new ArgumentNullException(nameof(subsystemData));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -49,6 +51,11 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
public string TypeDescription { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets subsystem data.
|
||||
/// </summary>
|
||||
public SubsystemData SubsystemData { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Complex[]? ConvertToComplexArray() => null;
|
||||
|
||||
|
@ -12,8 +12,6 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
internal class OpaqueLink : Opaque, IMatObject
|
||||
{
|
||||
private readonly SubsystemData subsystemData;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpaqueLink"/> class.
|
||||
/// </summary>
|
||||
@ -34,11 +32,10 @@ namespace MatFileHandler
|
||||
int[] indexToObjectId,
|
||||
int classIndex,
|
||||
SubsystemData subsystemData)
|
||||
: base(name, typeDescription, className, dimensions, data)
|
||||
: base(name, typeDescription, className, dimensions, data, subsystemData)
|
||||
{
|
||||
IndexToObjectId = indexToObjectId ?? throw new ArgumentNullException(nameof(indexToObjectId));
|
||||
ClassIndex = classIndex;
|
||||
this.subsystemData = subsystemData ?? throw new ArgumentNullException(nameof(subsystemData));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -74,9 +71,9 @@ namespace MatFileHandler
|
||||
/// <summary>
|
||||
/// Gets name of this object's class.
|
||||
/// </summary>
|
||||
public override string ClassName => subsystemData.ClassInformation[ClassIndex].Name;
|
||||
public override string ClassName => SubsystemData.ClassInformation[ClassIndex].Name;
|
||||
|
||||
private string[] FieldNamesArray => subsystemData.ClassInformation[ClassIndex].FieldNames.ToArray();
|
||||
private string[] FieldNamesArray => SubsystemData.ClassInformation[ClassIndex].FieldNames.ToArray();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IArray this[string field, params int[] list]
|
||||
@ -108,7 +105,7 @@ namespace MatFileHandler
|
||||
private bool TryGetValue(string field, out IArray? output, params int[] 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))
|
||||
{
|
||||
output = default;
|
||||
@ -122,9 +119,9 @@ namespace MatFileHandler
|
||||
}
|
||||
|
||||
var objectId = IndexToObjectId[index];
|
||||
var objectInfo = subsystemData.ObjectInformation[objectId];
|
||||
var objectInfo = SubsystemData.ObjectInformation[objectId];
|
||||
var fieldId = objectInfo.FieldLinks[fieldIndex];
|
||||
output = subsystemData.Data[fieldId];
|
||||
output = SubsystemData.Data[fieldId];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,18 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
/// <param name="classInformation">Information about the classes.</param>
|
||||
/// <param name="objectInformation">Information about the objects.</param>
|
||||
/// <param name="fieldNames">Field names.</param>
|
||||
/// <param name="data">Field values.</param>
|
||||
public SubsystemData(
|
||||
Dictionary<int, ClassInfo> classInformation,
|
||||
Dictionary<int, ObjectInfo> objectInformation,
|
||||
string[] fieldNames,
|
||||
Dictionary<int, IArray> data)
|
||||
{
|
||||
_realData = new RealSubsystemData(
|
||||
classInformation,
|
||||
objectInformation,
|
||||
fieldNames,
|
||||
data);
|
||||
}
|
||||
|
||||
@ -59,6 +62,12 @@ namespace MatFileHandler
|
||||
public Dictionary<int, ObjectInfo> ObjectInformation =>
|
||||
_realData?.ObjectInformation ?? throw new HandlerException("Subsystem data missing.");
|
||||
|
||||
/// <summary>
|
||||
/// Gets field names.
|
||||
/// </summary>
|
||||
public string[] FieldNames =>
|
||||
_realData?.FieldNames ?? throw new HandlerException("Subsystem data missing.");
|
||||
|
||||
/// <summary>
|
||||
/// Initialize this object from another object.
|
||||
/// This ugly hack allows us to read the opaque objects and store references to
|
||||
@ -71,6 +80,7 @@ namespace MatFileHandler
|
||||
_realData = new RealSubsystemData(
|
||||
data.ClassInformation,
|
||||
data.ObjectInformation,
|
||||
data.FieldNames,
|
||||
data.Data);
|
||||
}
|
||||
|
||||
@ -147,14 +157,17 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
/// <param name="classInformation">Class information.</param>
|
||||
/// <param name="objectInformation">Object information.</param>
|
||||
/// <param name="fieldNames">Field names.</param>
|
||||
/// <param name="data">Data.</param>
|
||||
public RealSubsystemData(
|
||||
Dictionary<int, ClassInfo> classInformation,
|
||||
Dictionary<int, ObjectInfo> objectInformation,
|
||||
string[] fieldNames,
|
||||
IReadOnlyDictionary<int, IArray> data)
|
||||
{
|
||||
ClassInformation = classInformation ?? throw new ArgumentNullException(nameof(classInformation));
|
||||
ObjectInformation = objectInformation ?? throw new ArgumentNullException(nameof(objectInformation));
|
||||
FieldNames = fieldNames;
|
||||
Data = data ?? throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
@ -172,6 +185,11 @@ namespace MatFileHandler
|
||||
/// Gets information about all the objects occurring in the file.
|
||||
/// </summary>
|
||||
public Dictionary<int, ObjectInfo> ObjectInformation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets field names.
|
||||
/// </summary>
|
||||
public string[] FieldNames { get; }
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -58,7 +59,7 @@ namespace MatFileHandler
|
||||
data[i] = TransformOpaqueData(opaqueData[i + 2], subsystemData);
|
||||
}
|
||||
|
||||
return new SubsystemData(classInformation, objectInformation, data);
|
||||
return new SubsystemData(classInformation, objectInformation, fieldNames, data);
|
||||
}
|
||||
|
||||
private static Dictionary<int, Dictionary<int, int>> ReadObjectPositionsToValues(byte[] info, int[] offsets, int numberOfObjectPositions)
|
||||
@ -303,20 +304,15 @@ namespace MatFileHandler
|
||||
{
|
||||
var next = BitConverter.ToInt32(bytes, position);
|
||||
position += 4;
|
||||
if (next == 0)
|
||||
if (next == bytes.Length)
|
||||
{
|
||||
if (position % 8 != 0)
|
||||
{
|
||||
position += 4;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
offsets.Add(next);
|
||||
}
|
||||
|
||||
return (offsets.ToArray(), position);
|
||||
return (offsets.ToArray(), 40);
|
||||
}
|
||||
|
||||
private static IArray TransformOpaqueData(IArray array, SubsystemData subsystemData)
|
||||
|
Loading…
x
Reference in New Issue
Block a user