From 5080f35e69e0ebe9718a1a0580da87164b274beb Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 8 Apr 2025 16:19:47 +0200 Subject: [PATCH] Even better handling of embedded objects --- MatFileHandler.Tests/MatFileReaderTests.cs | 26 +++++++++++- .../test-data/good/table-deep.mat | Bin 0 -> 1056 bytes MatFileHandler/ObjectParser.cs | 30 +++++++++++++ MatFileHandler/OpaqueLink.cs | 2 +- MatFileHandler/SubsystemDataReader.cs | 40 +++++++++++------- 5 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 MatFileHandler.Tests/test-data/good/table-deep.mat create mode 100644 MatFileHandler/ObjectParser.cs diff --git a/MatFileHandler.Tests/MatFileReaderTests.cs b/MatFileHandler.Tests/MatFileReaderTests.cs index 30ba7c2..f4d291d 100755 --- a/MatFileHandler.Tests/MatFileReaderTests.cs +++ b/MatFileHandler.Tests/MatFileReaderTests.cs @@ -388,6 +388,30 @@ namespace MatFileHandler.Tests Assert.Equal(new[] { 1.0, 3.0, 5.0, 2.0, 4.0, 6.0 }, variable2.ConvertToDoubleArray()); } + /// + /// Test reading a deeply nested table. + /// + [Theory, MemberData(nameof(TestDataFactories))] + public void TestDeepTable(AbstractTestDataFactory testFactory) + { + var matFile = testFactory["table-deep"]; + var obj = matFile["t"].Value as IMatObject; + var table = new TableAdapter(obj); + Assert.Equal(1, table.NumberOfRows); + Assert.Equal(2, table.NumberOfVariables); + Assert.Equal(new[] { "s", "another" }, table.VariableNames); + var s = table["s"] as IStructureArray; + Assert.Equal(new[] { "a", "b", "c" }, s.FieldNames); + var c = s["c", 0]; + var internalTable = new TableAdapter(c); + Assert.Equal(2, internalTable.NumberOfRows); + Assert.Equal(2, internalTable.NumberOfVariables); + Assert.Equal(new[] { "x", "y" }, internalTable.VariableNames); + var y = new StringAdapter(internalTable["y"]); + Assert.Equal("3", y[0]); + Assert.Equal("abc", y[1]); + } + /// /// Test reading a table with strings /// @@ -607,4 +631,4 @@ namespace MatFileHandler.Tests Assert.Equal(new ComplexOf(limits[1], limits[0]), array[1]); } } -} \ No newline at end of file +} diff --git a/MatFileHandler.Tests/test-data/good/table-deep.mat b/MatFileHandler.Tests/test-data/good/table-deep.mat new file mode 100644 index 0000000000000000000000000000000000000000..37c70e73f71a3c7417b244ea75c0b95eb0d1dfa2 GIT binary patch literal 1056 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2c0*X01nwjV*I2WZRmZYXA zY#a$JhlC8y9(wTljrrCCFp;i{}%a+~~RIM?4wp(nU-pk)rm!4~!$*a$gzkSo8 zOip``@v7IHVXsy%dUIjncTJ_l7q0H^UG?8f&dC4v{;Gb=LS^6cXXkgnPW!m7DqQ^Q zCXMt(G2KPlr=~I7?Y>lWS*eg&NLb+wSA|Sq8CQ-&EuRjTo@EES@;>z|+(Lx{{UN-I z6`lx8e!P&~Y^CI{O{|YsY_t-)yYa!+9c_8H7#HV0%C+<9nWA>+r0M$A+varJiT5kq z6~7thD6{i@RlaqX{_X6xSn-={6?d1WY;UyqamHlg-D#cTNW}R@?{LjD8CcnRP&VIPuvSz++_g~G02L4(;t1Q`1$5QVF=bm^|zn<$K+mrQ+ z#rE{2{*Cqjn0|Y^Z_E1gAFhk8U0?iZoyhz2#W%_y@4S?M!sG|$!ea9n2orn(31D$ANG zW*oXCcgin>UG~zCtm*Un{yd4g{q2XR%i)TYl%$+vCaUVjzGqHGGAOd&>E8Bqd#2MC zc@v>|Z!Hr{o`w0@Cm5zaPujHWxQ%#j`LBPwR)w~;KYr?eZt_h2kdyji>+eqbe){k1 z$ifw=GVND;tK;^&zCSD<{NeMR^sQ%hWPLE)G3Q6!&5GO;=iFae36<2GF}AmfE0*`E zk^b2At1{zH`SKffdkeab&VA+vED$r_D=tYgL=3Zocy;YU&gH)c4Ex&;5VL z=VQ3*zr(tZw|tx>8MjJU>_~dtmJ`ill^2xwrPe-H;*Wab_}^cy#GG~g^*tVU9FO^Z z+)$`^H~vXRYF&S*ZMzK6Lxv?RvM0@RvXK T+n)13{b&31PtxyR`?Uf9>TT*H literal 0 HcmV?d00001 diff --git a/MatFileHandler/ObjectParser.cs b/MatFileHandler/ObjectParser.cs new file mode 100644 index 0000000..c799074 --- /dev/null +++ b/MatFileHandler/ObjectParser.cs @@ -0,0 +1,30 @@ +// Copyright 2017-2018 Alexander Luzgarev + +namespace MatFileHandler +{ + /// + /// Parser for object data. + /// + internal static class ObjectParser + { + /// + /// Parse object data. + /// + /// Opaque link array. + /// Current subsystem data. + /// Parsed object. + public static IArray ParseObject(MatNumericalArrayOf uintArray, SubsystemData subsystemData) + { + var (dimensions, indexToObjectId, classIndex) = DataElementReader.ParseOpaqueData(uintArray.Data); + return new OpaqueLink( + uintArray.Name, + string.Empty, + string.Empty, + dimensions, + uintArray, + indexToObjectId, + classIndex, + subsystemData); + } + } +} diff --git a/MatFileHandler/OpaqueLink.cs b/MatFileHandler/OpaqueLink.cs index 003b4dc..803048d 100644 --- a/MatFileHandler/OpaqueLink.cs +++ b/MatFileHandler/OpaqueLink.cs @@ -186,4 +186,4 @@ namespace MatFileHandler } } } -} \ No newline at end of file +} diff --git a/MatFileHandler/SubsystemDataReader.cs b/MatFileHandler/SubsystemDataReader.cs index aca0bcd..980fabc 100644 --- a/MatFileHandler/SubsystemDataReader.cs +++ b/MatFileHandler/SubsystemDataReader.cs @@ -317,21 +317,11 @@ namespace MatFileHandler private static IArray TransformOpaqueData(IArray array, SubsystemData subsystemData) { - if (array is MatNumericalArrayOf uintArray) + if (array is MatNumericalArrayOf uintArray && + uintArray.Data.Length == 6 && + uintArray.Data[0] == 3707764736u) { - if (uintArray.Data[0] == 3707764736u) - { - var (dimensions, indexToObjectId, classIndex) = DataElementReader.ParseOpaqueData(uintArray.Data); - return new OpaqueLink( - uintArray.Name, - string.Empty, - string.Empty, - dimensions, - uintArray, - indexToObjectId, - classIndex, - subsystemData); - } + return ObjectParser.ParseObject(uintArray, subsystemData); } if (array is MatCellArray cellArray) @@ -344,6 +334,26 @@ namespace MatFileHandler } } + if (array is MatStructureArray structureArray) + { + var newFields = new Dictionary>(); + foreach (var pair in structureArray.Fields) + { + var values = pair.Value; + var transformedValues = new List(values.Count); + foreach (var value in values) + { + var transformedValue = TransformOpaqueData(value, subsystemData); + transformedValues.Add(transformedValue); + } + newFields[pair.Key] = transformedValues; + } + foreach (var pair in newFields) + { + structureArray.Fields[pair.Key] = pair.Value; + } + } + return array; } @@ -402,4 +412,4 @@ namespace MatFileHandler => _keyFromEmbeddedObjectPosition[embeddedObjectPosition]; } } -} \ No newline at end of file +}