From 2773f4c89851920db4324a662a840ed1bca60bec Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sun, 29 Sep 2019 20:11:33 +0200 Subject: [PATCH 1/8] Un-target net461 --- MatFileHandler/MatFileHandler.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatFileHandler/MatFileHandler.csproj b/MatFileHandler/MatFileHandler.csproj index 6e87fc5..6022143 100755 --- a/MatFileHandler/MatFileHandler.csproj +++ b/MatFileHandler/MatFileHandler.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net461 + netstandard2.0 1.3.0-beta4 MatFileHandler A library for reading and writing MATLAB .mat files. -- 2.45.2 From 6f4f40e7a4e21b175522fdc4befb339042c51e09 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sun, 29 Sep 2019 20:11:49 +0200 Subject: [PATCH 2/8] Target .NET Core 3.0 in test project --- MatFileHandler.Tests/MatFileHandler.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatFileHandler.Tests/MatFileHandler.Tests.csproj b/MatFileHandler.Tests/MatFileHandler.Tests.csproj index 1d96afa..c2d6c98 100755 --- a/MatFileHandler.Tests/MatFileHandler.Tests.csproj +++ b/MatFileHandler.Tests/MatFileHandler.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp2.0 + netcoreapp3.0 false -- 2.45.2 From b842bc7be15322a79745b674cd428adac1cd81fb Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sun, 29 Sep 2019 20:12:13 +0200 Subject: [PATCH 3/8] Enable nullable reference types --- MatFileHandler/MatFileHandler.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MatFileHandler/MatFileHandler.csproj b/MatFileHandler/MatFileHandler.csproj index 6022143..be03346 100755 --- a/MatFileHandler/MatFileHandler.csproj +++ b/MatFileHandler/MatFileHandler.csproj @@ -15,6 +15,8 @@ bin\$(Configuration)\ $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml true + 8.0 + enable ..\MatFileHandler.ruleset -- 2.45.2 From 1b465c2857ed52801ae60b22d13b2af8bbfc0cf5 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 5 Oct 2019 10:27:37 +0200 Subject: [PATCH 4/8] Rewrite DataExtraction --- MatFileHandler/DataElementConverter.cs | 32 +- MatFileHandler/DataExtraction.cs | 1214 +++++++++++++++++++++--- 2 files changed, 1116 insertions(+), 130 deletions(-) diff --git a/MatFileHandler/DataElementConverter.cs b/MatFileHandler/DataElementConverter.cs index 1a1e252..3a52952 100755 --- a/MatFileHandler/DataElementConverter.cs +++ b/MatFileHandler/DataElementConverter.cs @@ -33,8 +33,8 @@ namespace MatFileHandler DataElement data, DataElement imaginaryData) { - var realParts = DataExtraction.GetDataAsDouble(data).ToArrayLazily(); - var imaginaryParts = DataExtraction.GetDataAsDouble(imaginaryData).ToArrayLazily(); + var realParts = DataExtraction.GetDataAsDouble(data); + var imaginaryParts = DataExtraction.GetDataAsDouble(imaginaryData); if (realParts == null) { throw new HandlerException("Couldn't read sparse array."); @@ -111,7 +111,7 @@ namespace MatFileHandler { 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(flags, dimensions, name, data); } switch (flags.Class) @@ -163,7 +163,7 @@ namespace MatFileHandler string name, MiNum dataElement) { - var data = dataElement?.Data; + var data = dataElement.Data; return new MatCharArrayOf(flags, dimensions, name, data, Encoding.UTF8.GetString(data)); } @@ -172,25 +172,25 @@ namespace MatFileHandler switch (arrayType) { case ArrayType.MxDouble: - return DataExtraction.GetDataAsDouble(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsDouble(data) as T[]; case ArrayType.MxSingle: - return DataExtraction.GetDataAsSingle(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsSingle(data) as T[]; case ArrayType.MxInt8: - return DataExtraction.GetDataAsInt8(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsInt8(data) as T[]; case ArrayType.MxUInt8: - return DataExtraction.GetDataAsUInt8(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsUInt8(data) as T[]; case ArrayType.MxInt16: - return DataExtraction.GetDataAsInt16(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsInt16(data) as T[]; case ArrayType.MxUInt16: - return DataExtraction.GetDataAsUInt16(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsUInt16(data) as T[]; case ArrayType.MxInt32: - return DataExtraction.GetDataAsInt32(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsInt32(data) as T[]; case ArrayType.MxUInt32: - return DataExtraction.GetDataAsUInt32(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsUInt32(data) as T[]; case ArrayType.MxInt64: - return DataExtraction.GetDataAsInt64(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsInt64(data) as T[]; case ArrayType.MxUInt64: - return DataExtraction.GetDataAsUInt64(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsUInt64(data) as T[]; default: throw new NotSupportedException(); } @@ -200,12 +200,12 @@ namespace MatFileHandler { 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) { case MiNum _: - return DataExtraction.GetDataAsDouble(data).ToArrayLazily() as T[]; + return DataExtraction.GetDataAsDouble(data) as T[]; default: throw new NotSupportedException(); } diff --git a/MatFileHandler/DataExtraction.cs b/MatFileHandler/DataExtraction.cs index d5d9edd..a975acc 100755 --- a/MatFileHandler/DataExtraction.cs +++ b/MatFileHandler/DataExtraction.cs @@ -1,8 +1,6 @@ // Copyright 2017-2018 Alexander Luzgarev using System; -using System.Collections.Generic; -using System.Linq; namespace MatFileHandler { @@ -11,45 +9,33 @@ namespace MatFileHandler /// internal static class DataExtraction { - /// - /// Convert IEnumerable to array. - /// - /// Element type. - /// Input IEnumerable. - /// An equivalent array. - /// In contrast to the stanard ToArray() method, this doesn't create a copy if the input already was an array. - public static T[] ToArrayLazily(this IEnumerable somethingEnumerable) - { - return somethingEnumerable as T[] ?? somethingEnumerable.ToArray(); - } - /// /// Convert the contents of the Matlab data element to a sequence of Double values. /// /// Data element. /// Contents of the elements, converted to Double. - public static IEnumerable GetDataAsDouble(DataElement element) + public static double[] GetDataAsDouble(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToDouble); + return SbyteToDouble(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToDouble); + return ByteToDouble(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToDouble); + return IntToDouble(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToDouble); + return UintToDouble(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToDouble); + return ShortToDouble(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToDouble); + return UshortToDouble(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToDouble); + return LongToDouble(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToDouble); + return UlongToDouble(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToDouble); + return FloatToDouble(floatElement.Data); case MiNum doubleElement: return doubleElement.Data; } @@ -62,30 +48,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to Single. - public static IEnumerable GetDataAsSingle(DataElement element) + public static float[] GetDataAsSingle(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToSingle); + return SbyteToSingle(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToSingle); + return ByteToSingle(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToSingle); + return IntToSingle(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToSingle); + return UintToSingle(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToSingle); + return ShortToSingle(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToSingle); + return UshortToSingle(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToSingle); + return LongToSingle(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToSingle); + return UlongToSingle(ulongElement.Data); case MiNum floatElement: return floatElement.Data; case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToSingle); + return DoubleToSingle(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to float, found {element.GetType()}."); @@ -96,30 +82,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to Int8. - public static IEnumerable GetDataAsInt8(DataElement element) + public static sbyte[] GetDataAsInt8(DataElement element) { switch (element) { case MiNum sbyteElement: return sbyteElement.Data; case MiNum byteElement: - return byteElement.Data.Select(Convert.ToSByte); + return ByteToSByte(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToSByte); + return IntToSByte(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToSByte); + return UintToSByte(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToSByte); + return ShortToSByte(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToSByte); + return UshortToSByte(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToSByte); + return LongToSByte(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToSByte); + return UlongToSByte(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToSByte); + return SingleToSByte(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToSByte); + return DoubleToSByte(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to int8, found {element.GetType()}."); @@ -130,30 +116,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to UInt8. - public static IEnumerable GetDataAsUInt8(DataElement element) + public static byte[] GetDataAsUInt8(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToByte); + return SbyteToByte(sbyteElement.Data); case MiNum byteElement: return byteElement.Data; case MiNum intElement: - return intElement.Data.Select(Convert.ToByte); + return IntToByte(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToByte); + return UintToByte(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToByte); + return ShortToByte(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToByte); + return UshortToByte(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToByte); + return LongToByte(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToByte); + return UlongToByte(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToByte); + return SingleToByte(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToByte); + return DoubleToByte(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to uint8, found {element.GetType()}."); @@ -164,30 +150,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to Int16. - public static IEnumerable GetDataAsInt16(DataElement element) + public static short[] GetDataAsInt16(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToInt16); + return SbyteToInt16(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToInt16); + return ByteToInt16(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToInt16); + return IntToInt16(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToInt16); + return UintToInt16(uintElement.Data); case MiNum shortElement: return shortElement.Data; case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToInt16); + return UshortToInt16(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToInt16); + return LongToInt16(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToInt16); + return UlongToInt16(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToInt16); + return SingleToInt16(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToInt16); + return DoubleToInt16(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to int16, found {element.GetType()}."); @@ -198,30 +184,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to UInt16. - public static IEnumerable GetDataAsUInt16(DataElement element) + public static ushort[] GetDataAsUInt16(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToUInt16); + return SbyteToUInt16(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToUInt16); + return ByteToUInt16(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToUInt16); + return IntToUInt16(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToUInt16); + return UintToUInt16(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToUInt16); + return ShortToUInt16(shortElement.Data); case MiNum ushortElement: return ushortElement.Data; case MiNum longElement: - return longElement.Data.Select(Convert.ToUInt16); + return LongToUInt16(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToUInt16); + return UlongToUInt16(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToUInt16); + return SingleToUInt16(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToUInt16); + return DoubleToUInt16(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to uint16, found {element.GetType()}."); @@ -232,30 +218,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to Int32. - public static IEnumerable GetDataAsInt32(DataElement element) + public static int[] GetDataAsInt32(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToInt32); + return SbyteToInt32(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToInt32); + return ByteToInt32(byteElement.Data); case MiNum intElement: return intElement.Data; case MiNum uintElement: - return uintElement.Data.Select(Convert.ToInt32); + return UintToInt32(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToInt32); + return ShortToInt32(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToInt32); + return UshortToInt32(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToInt32); + return LongToInt32(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToInt32); + return UlongToInt32(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToInt32); + return SingleToInt32(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToInt32); + return DoubleToInt32(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to int32, found {element.GetType()}."); @@ -266,30 +252,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to UInt32. - public static IEnumerable GetDataAsUInt32(DataElement element) + public static uint[] GetDataAsUInt32(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToUInt32); + return SbyteToUInt32(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToUInt32); + return ByteToUInt32(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToUInt32); + return IntToUInt32(intElement.Data); case MiNum uintElement: return uintElement.Data; case MiNum shortElement: - return shortElement.Data.Select(Convert.ToUInt32); + return ShortToUInt32(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToUInt32); + return UshortToUInt32(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToUInt32); + return LongToUInt32(longElement.Data); case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToUInt32); + return UlongToUInt32(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToUInt32); + return SingleToUInt32(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToUInt32); + return DoubleToUInt32(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to uint32, found {element.GetType()}."); @@ -300,30 +286,30 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to Int64. - public static IEnumerable GetDataAsInt64(DataElement element) + public static long[] GetDataAsInt64(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToInt64); + return SbyteToInt64(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToInt64); + return ByteToInt64(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToInt64); + return IntToInt64(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToInt64); + return UintToInt64(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToInt64); + return ShortToInt64(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToInt64); + return UshortToInt64(ushortElement.Data); case MiNum longElement: return longElement.Data; case MiNum ulongElement: - return ulongElement.Data.Select(Convert.ToInt64); + return UlongToInt64(ulongElement.Data); case MiNum floatElement: - return floatElement.Data.Select(Convert.ToInt64); + return SingleToInt64(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToInt64); + return DoubleToInt64(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to int64, found {element.GetType()}."); @@ -334,33 +320,1033 @@ namespace MatFileHandler /// /// Data element. /// Contents of the elements, converted to UInt64. - public static IEnumerable GetDataAsUInt64(DataElement element) + public static ulong[] GetDataAsUInt64(DataElement element) { switch (element) { case MiNum sbyteElement: - return sbyteElement.Data.Select(Convert.ToUInt64); + return SbyteToUInt64(sbyteElement.Data); case MiNum byteElement: - return byteElement.Data.Select(Convert.ToUInt64); + return ByteToUInt64(byteElement.Data); case MiNum intElement: - return intElement.Data.Select(Convert.ToUInt64); + return IntToUInt64(intElement.Data); case MiNum uintElement: - return uintElement.Data.Select(Convert.ToUInt64); + return UintToUInt64(uintElement.Data); case MiNum shortElement: - return shortElement.Data.Select(Convert.ToUInt64); + return ShortToUInt64(shortElement.Data); case MiNum ushortElement: - return ushortElement.Data.Select(Convert.ToUInt64); + return UshortToUInt64(ushortElement.Data); case MiNum longElement: - return longElement.Data.Select(Convert.ToUInt64); + return LongToUInt64(longElement.Data); case MiNum ulongElement: return ulongElement.Data; case MiNum floatElement: - return floatElement.Data.Select(Convert.ToUInt64); + return SingleToUInt64(floatElement.Data); case MiNum doubleElement: - return doubleElement.Data.Select(Convert.ToUInt64); + return DoubleToUInt64(doubleElement.Data); } throw new HandlerException( $"Expected data element that would be convertible to uint64, found {element.GetType()}."); } + + // * to double + private static double[] SbyteToDouble(sbyte[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] ByteToDouble(byte[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] ShortToDouble(short[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] UshortToDouble(ushort[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] IntToDouble(int[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] UintToDouble(uint[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] LongToDouble(long[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] UlongToDouble(ulong[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + private static double[] FloatToDouble(float[] source) + { + var result = new double[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToDouble(source[i]); + } + + return result; + } + + // * to single + private static float[] SbyteToSingle(sbyte[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] ByteToSingle(byte[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] ShortToSingle(short[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] UshortToSingle(ushort[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] IntToSingle(int[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] UintToSingle(uint[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] LongToSingle(long[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] UlongToSingle(ulong[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + private static float[] DoubleToSingle(double[] source) + { + var result = new float[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSingle(source[i]); + } + + return result; + } + + // * to sbyte + private static sbyte[] ByteToSByte(byte[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] ShortToSByte(short[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] UshortToSByte(ushort[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] IntToSByte(int[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] UintToSByte(uint[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] LongToSByte(long[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] UlongToSByte(ulong[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] SingleToSByte(float[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + private static sbyte[] DoubleToSByte(double[] source) + { + var result = new sbyte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToSByte(source[i]); + } + + return result; + } + + // * to byte + private static byte[] SbyteToByte(sbyte[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] SingleToByte(float[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] ShortToByte(short[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] UshortToByte(ushort[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] IntToByte(int[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] UintToByte(uint[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] LongToByte(long[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] UlongToByte(ulong[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + private static byte[] DoubleToByte(double[] source) + { + var result = new byte[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToByte(source[i]); + } + + return result; + } + + // * to int16 + private static short[] SbyteToInt16(sbyte[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] ByteToInt16(byte[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] UshortToInt16(ushort[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] IntToInt16(int[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] UintToInt16(uint[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] LongToInt16(long[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] UlongToInt16(ulong[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] SingleToInt16(float[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + private static short[] DoubleToInt16(double[] source) + { + var result = new short[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt16(source[i]); + } + + return result; + } + + // * to uint16 + private static ushort[] SbyteToUInt16(sbyte[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] ByteToUInt16(byte[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] ShortToUInt16(short[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] IntToUInt16(int[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] UintToUInt16(uint[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] LongToUInt16(long[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] UlongToUInt16(ulong[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] SingleToUInt16(float[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + private static ushort[] DoubleToUInt16(double[] source) + { + var result = new ushort[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt16(source[i]); + } + + return result; + } + + // * to int32 + private static int[] SbyteToInt32(sbyte[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] ByteToInt32(byte[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] ShortToInt32(short[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] UshortToInt32(ushort[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] UintToInt32(uint[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] LongToInt32(long[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] UlongToInt32(ulong[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] SingleToInt32(float[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + private static int[] DoubleToInt32(double[] source) + { + var result = new int[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt32(source[i]); + } + + return result; + } + + // * to uint32 + private static uint[] SbyteToUInt32(sbyte[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] ByteToUInt32(byte[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] ShortToUInt32(short[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] UshortToUInt32(ushort[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] IntToUInt32(int[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] LongToUInt32(long[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] UlongToUInt32(ulong[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] SingleToUInt32(float[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + private static uint[] DoubleToUInt32(double[] source) + { + var result = new uint[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt32(source[i]); + } + + return result; + } + + // * to int64 + private static long[] SbyteToInt64(sbyte[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] ByteToInt64(byte[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] ShortToInt64(short[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] UshortToInt64(ushort[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] IntToInt64(int[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] UintToInt64(uint[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] UlongToInt64(ulong[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] SingleToInt64(float[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + private static long[] DoubleToInt64(double[] source) + { + var result = new long[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToInt64(source[i]); + } + + return result; + } + + // * to uint64 + private static ulong[] SbyteToUInt64(sbyte[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] ByteToUInt64(byte[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] ShortToUInt64(short[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] UshortToUInt64(ushort[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] IntToUInt64(int[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] UintToUInt64(uint[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] LongToUInt64(long[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] SingleToUInt64(float[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } + + private static ulong[] DoubleToUInt64(double[] source) + { + var result = new ulong[source.Length]; + for (var i = 0; i < source.Length; i++) + { + result[i] = Convert.ToUInt64(source[i]); + } + + return result; + } } } \ No newline at end of file -- 2.45.2 From aa9f62c4dfbf15e61116f2eff1580546b5b5dedc Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 5 Oct 2019 11:04:03 +0200 Subject: [PATCH 5/8] Upgrade analyzers --- MatFileHandler/MatFileHandler.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatFileHandler/MatFileHandler.csproj b/MatFileHandler/MatFileHandler.csproj index be03346..232b6d3 100755 --- a/MatFileHandler/MatFileHandler.csproj +++ b/MatFileHandler/MatFileHandler.csproj @@ -28,7 +28,7 @@ - + All -- 2.45.2 From d8f3ac09112337c5e3cc67e9734271210b52ccd6 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 5 Oct 2019 14:47:05 +0200 Subject: [PATCH 6/8] Nullable annotations --- MatFileHandler/DataElementConverter.cs | 58 ++++---- MatFileHandler/DataElementReader.cs | 15 ++- MatFileHandler/DataExtraction.cs | 64 +++++++-- MatFileHandler/DatetimeAdapter.cs | 30 +++-- MatFileHandler/DurationAdapter.cs | 3 +- MatFileHandler/HandlerException.cs | 4 +- MatFileHandler/IArray.cs | 4 +- MatFileHandler/IArrayOf.cs | 2 +- MatFileHandler/ISparseArrayOf.cs | 2 +- MatFileHandler/MatArray.cs | 4 +- MatFileHandler/MatFileReader.cs | 3 +- MatFileHandler/MatFileWriter.cs | 8 +- MatFileHandler/MatNumericalArrayOf.cs | 176 +++++++++++++++++++------ MatFileHandler/MatSparseArrayOf.cs | 6 +- MatFileHandler/MatStructureArray.cs | 22 +++- MatFileHandler/Opaque.cs | 4 +- MatFileHandler/OpaqueLink.cs | 28 +++- MatFileHandler/StringAdapter.cs | 3 +- MatFileHandler/SubsystemData.cs | 71 +++++++--- MatFileHandler/SubsystemDataReader.cs | 106 ++++++++------- MatFileHandler/TableAdapter.cs | 32 +++-- 21 files changed, 435 insertions(+), 210 deletions(-) diff --git a/MatFileHandler/DataElementConverter.cs b/MatFileHandler/DataElementConverter.cs index 3a52952..0aceeb6 100755 --- a/MatFileHandler/DataElementConverter.cs +++ b/MatFileHandler/DataElementConverter.cs @@ -106,7 +106,7 @@ namespace MatFileHandler int[] dimensions, string name, DataElement realData, - DataElement imaginaryData) + DataElement? imaginaryData) where T : struct { if (flags.Variable.HasFlag(Variable.IsLogical)) @@ -139,6 +139,11 @@ namespace MatFileHandler var dataArray = ConvertDataToProperType(realData, flags.Class); if (flags.Variable.HasFlag(Variable.IsComplex)) { + if (imaginaryData is null) + { + throw new HandlerException("Imaginary part of a complex variable not found."); + } + var dataArray2 = ConvertDataToProperType(imaginaryData, flags.Class); if (flags.Class == ArrayType.MxDouble) { @@ -169,34 +174,11 @@ namespace MatFileHandler private static T[] ConvertDataToProperType(DataElement data, ArrayType arrayType) { - switch (arrayType) - { - case ArrayType.MxDouble: - return DataExtraction.GetDataAsDouble(data) as T[]; - case ArrayType.MxSingle: - return DataExtraction.GetDataAsSingle(data) as T[]; - case ArrayType.MxInt8: - return DataExtraction.GetDataAsInt8(data) as T[]; - case ArrayType.MxUInt8: - return DataExtraction.GetDataAsUInt8(data) as T[]; - case ArrayType.MxInt16: - return DataExtraction.GetDataAsInt16(data) as T[]; - case ArrayType.MxUInt16: - return DataExtraction.GetDataAsUInt16(data) as T[]; - case ArrayType.MxInt32: - return DataExtraction.GetDataAsInt32(data) as T[]; - case ArrayType.MxUInt32: - return DataExtraction.GetDataAsUInt32(data) as T[]; - case ArrayType.MxInt64: - return DataExtraction.GetDataAsInt64(data) as T[]; - case ArrayType.MxUInt64: - return DataExtraction.GetDataAsUInt64(data) as T[]; - default: - throw new NotSupportedException(); - } + return TryConvertDataToProperType(data, arrayType) + ?? throw new HandlerException($"Unexpected data type."); } - private static T[] ConvertDataToSparseProperType(DataElement data, bool isLogical) + private static T[]? ConvertDataToSparseProperType(DataElement data, bool isLogical) { if (isLogical) { @@ -217,7 +199,7 @@ namespace MatFileHandler string name, MiNum dataElement) { - var data = dataElement?.Data; + var data = dataElement.Data; return new MatCharArrayOf( flags, dimensions, @@ -226,7 +208,7 @@ namespace MatFileHandler new string(data.Select(x => (char)x).ToArray())); } - private static Dictionary<(int, int), T> ConvertMatlabSparseToDictionary( + private static Dictionary<(int row, int column), T> ConvertMatlabSparseToDictionary( int[] rowIndex, int[] columnIndex, Func get) @@ -242,5 +224,23 @@ namespace MatFileHandler } return result; } + + private static T[]? TryConvertDataToProperType(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() + }; + } } } \ No newline at end of file diff --git a/MatFileHandler/DataElementReader.cs b/MatFileHandler/DataElementReader.cs index f01af12..b678566 100755 --- a/MatFileHandler/DataElementReader.cs +++ b/MatFileHandler/DataElementReader.cs @@ -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 typeHi = type >> 16; @@ -222,7 +222,8 @@ namespace MatFileHandler var elements = new List(); 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); } @@ -319,8 +320,9 @@ namespace MatFileHandler string name, int fieldNameLength) { - var element = Read(reader); - var fieldNames = ReadFieldNames(element as MiNum, fieldNameLength); + var element = Read(reader) as MiNum + ?? throw new HandlerException("Unable to parse structure field names."); + var fieldNames = ReadFieldNames(element, fieldNameLength); var fields = new Dictionary>(); foreach (var fieldName in fieldNames) { @@ -332,7 +334,8 @@ namespace MatFileHandler { 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); } } @@ -398,7 +401,7 @@ namespace MatFileHandler var element4 = Read(reader); var data = ReadData(element4); - DataElement imaginaryData = null; + DataElement? imaginaryData = null; if (flags.Variable.HasFlag(Variable.IsComplex)) { var element5 = Read(reader); diff --git a/MatFileHandler/DataExtraction.cs b/MatFileHandler/DataExtraction.cs index a975acc..455fd92 100755 --- a/MatFileHandler/DataExtraction.cs +++ b/MatFileHandler/DataExtraction.cs @@ -350,7 +350,13 @@ namespace MatFileHandler } // * to double - private static double[] SbyteToDouble(sbyte[] source) + + /// + /// Convert an array of signed bytes to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] SbyteToDouble(sbyte[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -361,7 +367,12 @@ namespace MatFileHandler return result; } - private static double[] ByteToDouble(byte[] source) + /// + /// Convert an array of bytes to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] ByteToDouble(byte[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -372,7 +383,12 @@ namespace MatFileHandler return result; } - private static double[] ShortToDouble(short[] source) + /// + /// Convert an array of shorts to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] ShortToDouble(short[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -383,7 +399,12 @@ namespace MatFileHandler return result; } - private static double[] UshortToDouble(ushort[] source) + /// + /// Convert an array of unsigned shorts to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] UshortToDouble(ushort[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -394,7 +415,12 @@ namespace MatFileHandler return result; } - private static double[] IntToDouble(int[] source) + /// + /// Convert an array of integers to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] IntToDouble(int[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -405,7 +431,12 @@ namespace MatFileHandler return result; } - private static double[] UintToDouble(uint[] source) + /// + /// Convert an array of unsigned integers to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] UintToDouble(uint[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -416,7 +447,12 @@ namespace MatFileHandler return result; } - private static double[] LongToDouble(long[] source) + /// + /// Convert an array of longs to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] LongToDouble(long[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -427,7 +463,12 @@ namespace MatFileHandler return result; } - private static double[] UlongToDouble(ulong[] source) + /// + /// Convert an array of unsigned longs to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] UlongToDouble(ulong[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) @@ -438,7 +479,12 @@ namespace MatFileHandler return result; } - private static double[] FloatToDouble(float[] source) + /// + /// Convert an array of floats to an array of doubles. + /// + /// Source array. + /// Converted array. + public static double[] FloatToDouble(float[] source) { var result = new double[source.Length]; for (var i = 0; i < source.Length; i++) diff --git a/MatFileHandler/DatetimeAdapter.cs b/MatFileHandler/DatetimeAdapter.cs index bdac59f..5f0f604 100644 --- a/MatFileHandler/DatetimeAdapter.cs +++ b/MatFileHandler/DatetimeAdapter.cs @@ -30,20 +30,24 @@ namespace MatFileHandler } epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - var dataArray = matObject["data", 0] as IArrayOf; - if (dataArray is null) + + switch (matObject["data", 0]) { - var dataComplex = matObject["data", 0] as IArrayOf; - var complexData = dataComplex.ConvertToComplexArray(); - data = complexData.Select(c => c.Real).ToArray(); - data2 = complexData.Select(c => c.Imaginary).ToArray(); - dimensions = dataComplex.Dimensions; - } - else - { - data = dataArray.ConvertToDoubleArray(); - data2 = new double[data.Length]; - dimensions = dataArray.Dimensions; + case IArrayOf dataArray: + data = dataArray.ConvertToDoubleArray() + ?? throw new HandlerException("Cannot extract data for the datetime adapter."); + data2 = new double[data.Length]; + dimensions = dataArray.Dimensions; + break; + case IArrayOf dataComplex: + var complexData = dataComplex.ConvertToComplexArray() + ?? throw new HandlerException("Cannot extract data for the datetime adapter."); + data = complexData.Select(c => c.Real).ToArray(); + data2 = complexData.Select(c => c.Imaginary).ToArray(); + dimensions = dataComplex.Dimensions; + break; + default: + throw new HandlerException("Datetime data not found."); } } diff --git a/MatFileHandler/DurationAdapter.cs b/MatFileHandler/DurationAdapter.cs index c7a6a35..aad282e 100644 --- a/MatFileHandler/DurationAdapter.cs +++ b/MatFileHandler/DurationAdapter.cs @@ -25,7 +25,8 @@ namespace MatFileHandler } var dataObject = matObject["millis", 0]; - data = dataObject.ConvertToDoubleArray(); + data = dataObject.ConvertToDoubleArray() + ?? throw new HandlerException("Cannot extract data for the duration adapter."); dimensions = dataObject.Dimensions; } diff --git a/MatFileHandler/HandlerException.cs b/MatFileHandler/HandlerException.cs index 38ec92b..fbc6c96 100755 --- a/MatFileHandler/HandlerException.cs +++ b/MatFileHandler/HandlerException.cs @@ -5,7 +5,7 @@ using System; namespace MatFileHandler { /// - /// Exception related to Matlab data handling + /// Exception related to Matlab data handling. /// public class HandlerException : Exception { @@ -14,7 +14,7 @@ namespace MatFileHandler /// /// Error message. /// Inner exception. - public HandlerException(string message, Exception innerException = null) + public HandlerException(string message, Exception? innerException = null) : base(message, innerException) { } diff --git a/MatFileHandler/IArray.cs b/MatFileHandler/IArray.cs index adda6fb..a1e88b2 100755 --- a/MatFileHandler/IArray.cs +++ b/MatFileHandler/IArray.cs @@ -28,12 +28,12 @@ namespace MatFileHandler /// Tries to convert the array to an array of Double values. /// /// Array of values of the array, converted to Double, or null if the conversion is not possible. - double[] ConvertToDoubleArray(); + double[]? ConvertToDoubleArray(); /// /// Tries to convert the array to an array of Complex values. /// /// Array of values of the array, converted to Complex, or null if the conversion is not possible. - Complex[] ConvertToComplexArray(); + Complex[]? ConvertToComplexArray(); } } \ No newline at end of file diff --git a/MatFileHandler/IArrayOf.cs b/MatFileHandler/IArrayOf.cs index 49f4054..22a959a 100755 --- a/MatFileHandler/IArrayOf.cs +++ b/MatFileHandler/IArrayOf.cs @@ -21,7 +21,7 @@ namespace MatFileHandler /// * for cell arrays: /// IArray; /// * for structure arrays: - /// IReadOnlyDictionary<string, IArray>; + /// IReadOnlyDictionary<string, IArray>. /// public interface IArrayOf : IArray { diff --git a/MatFileHandler/ISparseArrayOf.cs b/MatFileHandler/ISparseArrayOf.cs index 74c77ae..83229d2 100755 --- a/MatFileHandler/ISparseArrayOf.cs +++ b/MatFileHandler/ISparseArrayOf.cs @@ -15,6 +15,6 @@ namespace MatFileHandler /// /// Gets a dictionary mapping indices to values. /// - new IReadOnlyDictionary<(int, int), T> Data { get; } + new IReadOnlyDictionary<(int row, int column), T> Data { get; } } } \ No newline at end of file diff --git a/MatFileHandler/MatArray.cs b/MatFileHandler/MatArray.cs index b35fa50..ecf0e1e 100755 --- a/MatFileHandler/MatArray.cs +++ b/MatFileHandler/MatArray.cs @@ -54,13 +54,13 @@ namespace MatFileHandler } /// - public virtual double[] ConvertToDoubleArray() + public virtual double[]? ConvertToDoubleArray() { return null; } /// - public virtual Complex[] ConvertToComplexArray() + public virtual Complex[]? ConvertToComplexArray() { return null; } diff --git a/MatFileHandler/MatFileReader.cs b/MatFileHandler/MatFileReader.cs index 0050272..a4e3ae6 100755 --- a/MatFileHandler/MatFileReader.cs +++ b/MatFileHandler/MatFileReader.cs @@ -57,7 +57,8 @@ namespace MatFileHandler var dataElement = dataElementReader.Read(reader); if (position == subsystemDataOffset) { - var subsystemDataElement = dataElement as IArrayOf; + var subsystemDataElement = dataElement as IArrayOf + ?? throw new HandlerException("Cannot parse subsystem data element."); var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData); subsystemData.Set(newSubsystemData); } diff --git a/MatFileHandler/MatFileWriter.cs b/MatFileHandler/MatFileWriter.cs index 414ab39..4f9a932 100755 --- a/MatFileHandler/MatFileWriter.cs +++ b/MatFileHandler/MatFileWriter.cs @@ -198,14 +198,14 @@ namespace MatFileHandler return buffer; } - private (byte[], byte[]) ConvertToPairOfByteArrays(ComplexOf[] data) + private (byte[] real, byte[] imaginary) ConvertToPairOfByteArrays(ComplexOf[] data) where T : struct { return (ConvertToByteArray(data.Select(x => x.Real).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()), ConvertToByteArray(data.Select(x => x.Imaginary).ToArray())); @@ -496,8 +496,8 @@ namespace MatFileHandler for (var column = 0; column < numberOfColumns; column++) { var column1 = column; - var thisColumn = keys.Where(pair => pair.Item2 == column1 && !dict[pair].Equals(default(T))); - var thisRow = thisColumn.Select(pair => pair.Item1).OrderBy(x => x).ToArray(); + var thisColumn = keys.Where(pair => pair.column == column1 && !dict[pair].Equals(default)); + var thisRow = thisColumn.Select(pair => pair.row).OrderBy(x => x).ToArray(); rowIndexList.AddRange(thisRow); valuesList.AddRange(thisRow.Select(row => dict[(row, column1)])); columnIndex[column + 1] = rowIndexList.Count; diff --git a/MatFileHandler/MatNumericalArrayOf.cs b/MatFileHandler/MatNumericalArrayOf.cs index 80bde49..0fce0c3 100755 --- a/MatFileHandler/MatNumericalArrayOf.cs +++ b/MatFileHandler/MatNumericalArrayOf.cs @@ -43,58 +43,152 @@ namespace MatFileHandler /// Array of values of the array, converted to Double, or null if the conversion is not possible. 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.") + }; } /// /// Tries to convert the array to an array of Complex values. /// /// Array of values of the array, converted to Complex, or null if the conversion is not possible. - public override Complex[] ConvertToComplexArray() + public override Complex[]? ConvertToComplexArray() { - if (Data is Complex[]) + return Data switch { - return Data as Complex[]; - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - if (Data is ComplexOf[]) - { - return ConvertToComplex(Data as ComplexOf[]); - } - return ConvertToDoubleArray().Select(x => new Complex(x, 0.0)).ToArray(); + Complex[] data => data, + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + ComplexOf[] ofs => ConvertToComplex(ofs), + _ => ConvertToComplex(ConvertToDoubleArray()) + }; } - private static Complex[] ConvertToComplex(IEnumerable> array) - where TS : struct + private static Complex[] ConvertToComplex(ComplexOf[] array) { - 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[] 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[] 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[] 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[] 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[] 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[] 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[] 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[] 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; } } } \ No newline at end of file diff --git a/MatFileHandler/MatSparseArrayOf.cs b/MatFileHandler/MatSparseArrayOf.cs index db9fd5d..8c60e4e 100755 --- a/MatFileHandler/MatSparseArrayOf.cs +++ b/MatFileHandler/MatSparseArrayOf.cs @@ -26,7 +26,7 @@ namespace MatFileHandler SparseArrayFlags flags, int[] dimensions, string name, - Dictionary<(int, int), T> data) + Dictionary<(int row, int column), T> data) : base(flags.ArrayFlags, dimensions, name) { DataDictionary = data; @@ -39,9 +39,9 @@ namespace MatFileHandler .ToArray(); /// - 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; } /// public T this[params int[] list] diff --git a/MatFileHandler/MatStructureArray.cs b/MatFileHandler/MatStructureArray.cs index 9422d06..9a91530 100755 --- a/MatFileHandler/MatStructureArray.cs +++ b/MatFileHandler/MatStructureArray.cs @@ -35,7 +35,19 @@ namespace MatFileHandler /// /// Gets null: not implemented. /// - public IReadOnlyDictionary[] Data => null; + public IReadOnlyDictionary[] Data + { + get + { + var result = new IReadOnlyDictionary[Count]; + for (var i = 0; i < Count; i++) + { + result[i] = FieldNames.ToDictionary(name => name, name => Fields[name][i]); + } + + return result; + } + } /// /// Gets a dictionary that maps field names to lists of values. @@ -128,7 +140,7 @@ namespace MatFileHandler /// /// Checks if the structure has a given field. /// - /// Field name + /// Field name. /// True iff the structure has a given field. public bool ContainsKey(string key) => Parent.Fields.ContainsKey(key); @@ -138,12 +150,14 @@ namespace MatFileHandler /// Field name. /// Value (or null if the field is not present). /// Success status of the query. - 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); if (!success) { - value = default(IArray); + value = default; return false; } value = array[Index]; diff --git a/MatFileHandler/Opaque.cs b/MatFileHandler/Opaque.cs index b574d22..9ce69b7 100644 --- a/MatFileHandler/Opaque.cs +++ b/MatFileHandler/Opaque.cs @@ -50,9 +50,9 @@ namespace MatFileHandler public string TypeDescription { get; } /// - public override Complex[] ConvertToComplexArray() => null; + public override Complex[]? ConvertToComplexArray() => null; /// - public override double[] ConvertToDoubleArray() => null; + public override double[]? ConvertToDoubleArray() => null; } } \ No newline at end of file diff --git a/MatFileHandler/OpaqueLink.cs b/MatFileHandler/OpaqueLink.cs index ed71d2f..563e96e 100644 --- a/MatFileHandler/OpaqueLink.cs +++ b/MatFileHandler/OpaqueLink.cs @@ -47,7 +47,21 @@ namespace MatFileHandler public int ClassIndex { get; } /// - public IReadOnlyDictionary[] Data => null; + public IReadOnlyDictionary[] Data + { + get + { + var result = new IReadOnlyDictionary[Count]; + for (var i = 0; i < Count; i++) + { + result[i] = FieldNamesArray.ToDictionary( + name => name, + name => this[name, i]); + } + + return result; + } + } /// public IEnumerable FieldNames => FieldNamesArray; @@ -71,7 +85,7 @@ namespace MatFileHandler { if (TryGetValue(field, out var result, list)) { - return result; + return result!; } throw new IndexOutOfRangeException(); @@ -91,19 +105,19 @@ namespace MatFileHandler 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 maybeFieldIndex = subsystemData.ClassInformation[ClassIndex].FindField(field); if (!(maybeFieldIndex is int fieldIndex)) { - output = default(IArray); + output = default; return false; } if (index >= IndexToObjectId.Length) { - output = default(IArray); + output = default; return false; } @@ -161,7 +175,9 @@ namespace MatFileHandler } /// - 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); } diff --git a/MatFileHandler/StringAdapter.cs b/MatFileHandler/StringAdapter.cs index afc5f80..8815d1c 100644 --- a/MatFileHandler/StringAdapter.cs +++ b/MatFileHandler/StringAdapter.cs @@ -25,7 +25,8 @@ namespace MatFileHandler throw new ArgumentException("The object provided is not a string."); } - var binaryData = matObject["any", 0] as IArrayOf; + var binaryData = matObject["any", 0] as IArrayOf + ?? throw new HandlerException("Cannot extract string data."); (dimensions, strings) = ParseBinaryData(binaryData.Data); } diff --git a/MatFileHandler/SubsystemData.cs b/MatFileHandler/SubsystemData.cs index fd987b8..f14ffae 100644 --- a/MatFileHandler/SubsystemData.cs +++ b/MatFileHandler/SubsystemData.cs @@ -12,15 +12,15 @@ namespace MatFileHandler /// internal class SubsystemData { + private RealSubsystemData? _realData; + /// /// Initializes a new instance of the class. /// Default constructor: initializes everything to null. /// public SubsystemData() { - ClassInformation = null; - ObjectInformation = null; - Data = null; + _realData = null; } /// @@ -35,27 +35,29 @@ namespace MatFileHandler Dictionary objectInformation, Dictionary data) { - this.ClassInformation = - classInformation ?? throw new ArgumentNullException(nameof(classInformation)); - this.ObjectInformation = - objectInformation ?? throw new ArgumentNullException(nameof(objectInformation)); - this.Data = data ?? throw new ArgumentNullException(nameof(data)); + _realData = new RealSubsystemData( + classInformation, + objectInformation, + data); } /// - /// Gets or sets information about all the classes occurring in the file. + /// Gets information about all the classes occurring in the file. /// - public Dictionary ClassInformation { get; set; } + public Dictionary ClassInformation => + _realData?.ClassInformation ?? throw new HandlerException("Subsystem data missing."); /// - /// 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. /// - public IReadOnlyDictionary Data { get; set; } + public IReadOnlyDictionary Data => + _realData?.Data ?? throw new HandlerException("Subsystem data missing."); /// - /// Gets or sets information about all the objects occurring in the file. + /// Gets information about all the objects occurring in the file. /// - public Dictionary ObjectInformation { get; set; } + public Dictionary ObjectInformation => + _realData?.ObjectInformation ?? throw new HandlerException("Subsystem data missing."); /// /// Initialize this object from another object. @@ -66,9 +68,10 @@ namespace MatFileHandler /// Another subsystem data. public void Set(SubsystemData data) { - this.ClassInformation = data.ClassInformation; - this.ObjectInformation = data.ObjectInformation; - this.Data = data.Data; + _realData = new RealSubsystemData( + data.ClassInformation, + data.ObjectInformation, + data.Data); } /// @@ -136,5 +139,39 @@ namespace MatFileHandler /// public IReadOnlyDictionary FieldLinks => fieldLinks; } + + private class RealSubsystemData + { + /// + /// Initializes a new instance of the class. + /// + /// Class information. + /// Object information. + /// Data. + public RealSubsystemData( + Dictionary classInformation, + Dictionary objectInformation, + IReadOnlyDictionary data) + { + ClassInformation = classInformation ?? throw new ArgumentNullException(nameof(classInformation)); + ObjectInformation = objectInformation ?? throw new ArgumentNullException(nameof(objectInformation)); + Data = data ?? throw new ArgumentNullException(nameof(data)); + } + + /// + /// Gets information about all the classes occurring in the file. + /// + public Dictionary ClassInformation { get; } + + /// + /// Gets the actual data: mapping of "object field" indices to their values. + /// + public IReadOnlyDictionary Data { get; } + + /// + /// Gets information about all the objects occurring in the file. + /// + public Dictionary ObjectInformation { get; } + } } } \ No newline at end of file diff --git a/MatFileHandler/SubsystemDataReader.cs b/MatFileHandler/SubsystemDataReader.cs index 9b1b6fc..229bc82 100644 --- a/MatFileHandler/SubsystemDataReader.cs +++ b/MatFileHandler/SubsystemDataReader.cs @@ -23,65 +23,27 @@ namespace MatFileHandler /// Subsystem data read. public static SubsystemData Read(byte[] bytes, SubsystemData subsystemData) { - List rawVariables = null; - using (var stream = new MemoryStream(bytes)) - { - using (var reader = new BinaryReader(stream)) - { - reader.ReadBytes(8); - rawVariables = MatFileReader.ReadRawVariables(reader, -1, subsystemData); - } - } + var rawVariables = ReadRawVariables(bytes, subsystemData); // Parse subsystem data. - var mainVariable = rawVariables[0].DataElement as IStructureArray; - var mcosData = mainVariable["MCOS", 0] as Opaque; - var opaqueData = mcosData.RawData as ICellArray; - var info = (opaqueData[0] as IArrayOf).Data; + var mainVariable = rawVariables[0].DataElement as IStructureArray + ?? throw new HandlerException("Subsystem data must be a structure array."); + var mcosData = mainVariable["MCOS", 0] as Opaque + ?? 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)?.Data + ?? throw new HandlerException("Opaque data info must be a byte array."); var (offsets, position) = ReadOffsets(info, 0); var fieldNames = ReadFieldNames(info, position, offsets[1]); var numberOfClasses = ((offsets[3] - offsets[2]) / 16) - 1; - Dictionary classIdToName = null; - using (var stream = new MemoryStream(info, offsets[2], offsets[3] - offsets[2])) - { - using (var reader = new BinaryReader(stream)) - { - classIdToName = ReadClassNames(reader, fieldNames, numberOfClasses); - } - } - + var classIdToName = ReadClassIdToName(info, offsets, fieldNames, numberOfClasses); var numberOfEmbeddedObjects = (offsets[4] - offsets[3] - 8) / 16; - Dictionary> embeddedObjectPositionsToValues = null; - using (var stream = new MemoryStream(info, offsets[3], offsets[4] - offsets[3])) - { - using (var reader = new BinaryReader(stream)) - { - embeddedObjectPositionsToValues = - ReadEmbeddedObjectPositionsToValuesMapping(reader, numberOfEmbeddedObjects); - } - } - + var embeddedObjectPositionsToValues = ReadEmbeddedObjectPositionsToValues(info, offsets, numberOfEmbeddedObjects); var numberOfObjects = ((offsets[5] - offsets[4]) / 24) - 1; - Dictionary objectClasses = null; - using (var stream = new MemoryStream(info, offsets[4], offsets[5] - offsets[4])) - { - using (var reader = new BinaryReader(stream)) - { - objectClasses = ReadObjectClasses(reader, numberOfObjects); - } - } - + var objectClasses = ReadObjectClassInformations(info, offsets, numberOfObjects); var numberOfObjectPositions = objectClasses.Values.Count(x => x.ObjectPosition != 0); - - Dictionary> 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 objectPositionsToValues = ReadObjectPositionsToValues(info, offsets, numberOfObjectPositions); var (classInformation, objectInformation) = GatherClassAndObjectInformation( classIdToName, @@ -89,7 +51,6 @@ namespace MatFileHandler objectClasses, objectPositionsToValues, embeddedObjectPositionsToValues); - var allFields = objectInformation.Values.SelectMany(obj => obj.FieldLinks.Values); var data = new Dictionary(); foreach (var i in allFields) @@ -100,7 +61,44 @@ namespace MatFileHandler return new SubsystemData(classInformation, objectInformation, data); } - private static (Dictionary, Dictionary) + private static Dictionary> 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 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> 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 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 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 classInfos, + Dictionary objectInfos) GatherClassAndObjectInformation( Dictionary classIdToName, string[] fieldNames, @@ -318,7 +316,7 @@ namespace MatFileHandler string.Empty, string.Empty, dimensions, - array as DataElement, + uintArray, indexToObjectId, classIndex, subsystemData); diff --git a/MatFileHandler/TableAdapter.cs b/MatFileHandler/TableAdapter.cs index f6aa641..1c4d44d 100644 --- a/MatFileHandler/TableAdapter.cs +++ b/MatFileHandler/TableAdapter.cs @@ -18,25 +18,34 @@ namespace MatFileHandler /// Source table object. public TableAdapter(IArray array) { - matObject = array as IMatObject; - if (matObject?.ClassName != "table") + matObject = array as IMatObject + ?? 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."); } - 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 .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(); NumberOfVariables = VariableNames.Length; - var props = matObject["props"] as IStructureArray; - Description = (props["Description"] as ICharArray).String; - NumberOfRows = (int)matObject["nrows"].ConvertToDoubleArray()[0]; - var rowNamesArrays = matObject["rownames"] as ICellArray; + var props = matObject["props"] as IStructureArray + ?? throw new HandlerException("Table properties must be a structure array."); + Description = (props["Description"] as ICharArray + ?? 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 .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(); } @@ -66,7 +75,7 @@ namespace MatFileHandler public string[] VariableNames { get; } /// - /// Gets all the data for a given variable + /// Gets all the data for a given variable. /// /// Variable name. /// All data associated with the variable. @@ -83,7 +92,8 @@ namespace MatFileHandler 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]; } } -- 2.45.2 From 662a2b97fb77998aad8b88ba047e40069c1c6ea8 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 5 Oct 2019 15:19:05 +0200 Subject: [PATCH 7/8] Update build definition --- azure-pipelines.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 13eecb1..c43e0ec 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,12 +4,17 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-latest' variables: buildConfiguration: 'Release' steps: +- task: UseDotNet@2 + displayName: 'Use .NET Core SDK 3.x' + inputs: + version: 3.x + - script: dotnet build --configuration $(buildConfiguration) displayName: 'dotnet build $(buildConfiguration)' -- 2.45.2 From f3a2559237c3bac55b1d380803cfb498bff4ddf9 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 5 Oct 2019 15:21:44 +0200 Subject: [PATCH 8/8] Target .NET Framework 4.6.1 again --- MatFileHandler/MatFileHandler.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatFileHandler/MatFileHandler.csproj b/MatFileHandler/MatFileHandler.csproj index 232b6d3..895ded3 100755 --- a/MatFileHandler/MatFileHandler.csproj +++ b/MatFileHandler/MatFileHandler.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.0;net461 1.3.0-beta4 MatFileHandler A library for reading and writing MATLAB .mat files. -- 2.45.2