diff --git a/MatFileHandler.Tests/MatFileReaderHdfTests.cs b/MatFileHandler.Tests/MatFileReaderHdfTests.cs
index 6e0a81a..5434423 100644
--- a/MatFileHandler.Tests/MatFileReaderHdfTests.cs
+++ b/MatFileHandler.Tests/MatFileReaderHdfTests.cs
@@ -1,10 +1,15 @@
-using System.IO;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System.IO;
using System.Linq;
using System.Numerics;
using NUnit.Framework;
namespace MatFileHandler.Tests
{
+ ///
+ /// Tests of file reading API (HDF cases).
+ ///
[TestFixture]
public class MatFileReaderHdfTests
{
diff --git a/MatFileHandler.Tests/MatFileReaderLevel5Tests.cs b/MatFileHandler.Tests/MatFileReaderLevel5Tests.cs
index 76689bf..188be0f 100644
--- a/MatFileHandler.Tests/MatFileReaderLevel5Tests.cs
+++ b/MatFileHandler.Tests/MatFileReaderLevel5Tests.cs
@@ -9,7 +9,7 @@ using NUnit.Framework;
namespace MatFileHandler.Tests
{
///
- /// Tests of file reading API.
+ /// Tests of file reading API (Level 5 cases).
///
[TestFixture]
public class MatFileReaderLevel5Tests
diff --git a/MatFileHandler/DataElementReader.cs b/MatFileHandler/DataElementReader.cs
index 9138b7b..407fa22 100755
--- a/MatFileHandler/DataElementReader.cs
+++ b/MatFileHandler/DataElementReader.cs
@@ -25,60 +25,15 @@ namespace MatFileHandler
this.subsystemData = subsystemData ?? throw new ArgumentNullException(nameof(subsystemData));
}
- private DataElement ReadElementWithoutFlags(Tag tag, BinaryReader reader)
- {
- switch (tag.Type)
- {
- case DataType.MiInt8:
- return ReadNum(tag, reader);
- case DataType.MiUInt8:
- case DataType.MiUtf8:
- return ReadNum(tag, reader);
- case DataType.MiInt16:
- return ReadNum(tag, reader);
- case DataType.MiUInt16:
- case DataType.MiUtf16:
- return ReadNum(tag, reader);
- case DataType.MiInt32:
- return ReadNum(tag, reader);
- case DataType.MiUInt32:
- return ReadNum(tag, reader);
- case DataType.MiSingle:
- return ReadNum(tag, reader);
- case DataType.MiDouble:
- return ReadNum(tag, reader);
- case DataType.MiInt64:
- return ReadNum(tag, reader);
- case DataType.MiUInt64:
- return ReadNum(tag, reader);
- default:
- throw new NotSupportedException("Unknown element.");
- }
- }
-
- private DataElementWithArrayFlags ReadElementWithFlags(Tag tag, BinaryReader reader)
- {
- switch (tag.Type)
- {
- case DataType.MiMatrix:
- return ReadMatrix(tag, reader);
- case DataType.MiCompressed:
- return ReadCompressed(tag, reader);
- default:
- var element = ReadElementWithoutFlags(tag, reader);
- return new DataElementWithArrayFlags(element);
- }
- }
-
///
/// Read a data element.
///
/// Input reader.
/// Data element.
- public DataElementWithArrayFlags Read(BinaryReader reader)
+ public DataElementWithMetadata Read(BinaryReader reader)
{
var (dataReader, tag) = ReadTag(reader);
- DataElementWithArrayFlags result = ReadElementWithFlags(tag, dataReader);
+ DataElementWithMetadata result = ReadElementWithFlags(tag, dataReader);
if (tag.Type != DataType.MiCompressed)
{
var position = reader.BaseStream.Position;
@@ -211,9 +166,7 @@ namespace MatFileHandler
private DataElement ContinueReadingCellArray(
BinaryReader reader,
- ArrayFlags flags,
- int[] dimensions,
- string name)
+ int[] dimensions)
{
var numberOfElements = dimensions.NumberOfElements();
var elements = new List();
@@ -226,7 +179,7 @@ namespace MatFileHandler
return new MatCellArray(dimensions, elements);
}
- private DataElementWithArrayFlags ContinueReadingOpaque(BinaryReader reader)
+ private DataElementWithMetadata ContinueReadingOpaque(BinaryReader reader)
{
var nameElement = Read(reader).Element as MiNum ??
throw new HandlerException("Unexpected type in object name.");
@@ -242,7 +195,7 @@ namespace MatFileHandler
if (data is MatNumericalArrayOf linkElement)
{
var (dimensions, indexToObjectId, classIndex) = ParseOpaqueData(linkElement.Data);
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
new OpaqueLink(
typeDescription,
className,
@@ -256,7 +209,7 @@ namespace MatFileHandler
}
else
{
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
new Opaque(
typeDescription,
className,
@@ -267,7 +220,7 @@ namespace MatFileHandler
}
}
- private DataElementWithArrayFlags ContinueReadingSparseArray(
+ private DataElementWithMetadata ContinueReadingSparseArray(
BinaryReader reader,
DataElement firstElement,
int[] dimensions,
@@ -281,7 +234,7 @@ namespace MatFileHandler
var data = Read(reader).Element;
if (arrayFlags.Variable.HasFlag(Variable.IsLogical))
{
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatSparseArrayOf(
arrayFlags,
dimensions,
@@ -296,7 +249,7 @@ namespace MatFileHandler
if (arrayFlags.Variable.HasFlag(Variable.IsComplex))
{
var imaginaryData = Read(reader).Element;
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatSparseArrayOfComplex(
dimensions,
rowIndex.Data,
@@ -311,7 +264,7 @@ namespace MatFileHandler
switch (data)
{
case MiNum _:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatSparseArrayOf(
arrayFlags,
dimensions,
@@ -352,7 +305,7 @@ namespace MatFileHandler
return new MatStructureArray(dimensions, fields);
}
- private DataElementWithArrayFlags Read(Stream stream)
+ private DataElementWithMetadata Read(Stream stream)
{
using (var reader = new BinaryReader(stream))
{
@@ -360,7 +313,7 @@ namespace MatFileHandler
}
}
- private DataElementWithArrayFlags ReadCompressed(Tag tag, BinaryReader reader)
+ private DataElementWithMetadata ReadCompressed(Tag tag, BinaryReader reader)
{
reader.ReadBytes(2);
var compressedData = new byte[tag.Length - 6];
@@ -379,11 +332,56 @@ namespace MatFileHandler
return Read(resultStream);
}
- private DataElementWithArrayFlags ReadMatrix(Tag tag, BinaryReader reader)
+ private DataElementWithMetadata ReadElementWithFlags(Tag tag, BinaryReader reader)
+ {
+ switch (tag.Type)
+ {
+ case DataType.MiMatrix:
+ return ReadMatrix(tag, reader);
+ case DataType.MiCompressed:
+ return ReadCompressed(tag, reader);
+ default:
+ var element = ReadElementWithoutFlags(tag, reader);
+ return new DataElementWithMetadata(element);
+ }
+ }
+
+ private DataElement ReadElementWithoutFlags(Tag tag, BinaryReader reader)
+ {
+ switch (tag.Type)
+ {
+ case DataType.MiInt8:
+ return ReadNum(tag, reader);
+ case DataType.MiUInt8:
+ case DataType.MiUtf8:
+ return ReadNum(tag, reader);
+ case DataType.MiInt16:
+ return ReadNum(tag, reader);
+ case DataType.MiUInt16:
+ case DataType.MiUtf16:
+ return ReadNum(tag, reader);
+ case DataType.MiInt32:
+ return ReadNum(tag, reader);
+ case DataType.MiUInt32:
+ return ReadNum(tag, reader);
+ case DataType.MiSingle:
+ return ReadNum(tag, reader);
+ case DataType.MiDouble:
+ return ReadNum(tag, reader);
+ case DataType.MiInt64:
+ return ReadNum(tag, reader);
+ case DataType.MiUInt64:
+ return ReadNum(tag, reader);
+ default:
+ throw new NotSupportedException("Unknown element.");
+ }
+ }
+
+ private DataElementWithMetadata ReadMatrix(Tag tag, BinaryReader reader)
{
if (tag.Length == 0)
{
- return new DataElementWithArrayFlags(MatArray.Empty());
+ return new DataElementWithMetadata(MatArray.Empty());
}
var element1 = Read(reader).Element;
@@ -403,7 +401,7 @@ namespace MatFileHandler
var name = ReadName(element3);
if (flags.Class == ArrayType.MxCell)
{
- return new DataElementWithArrayFlags(ContinueReadingCellArray(reader, flags, dimensions, name));
+ return new DataElementWithMetadata(ContinueReadingCellArray(reader, dimensions));
}
if (flags.Class == ArrayType.MxSparse)
@@ -425,7 +423,7 @@ namespace MatFileHandler
var fieldNameLengthElement = data as MiNum ??
throw new HandlerException(
"Unexpected type in structure field name length.");
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
ContinueReadingStructure(reader, dimensions, fieldNameLengthElement.Data[0]),
flags,
name);
@@ -437,7 +435,7 @@ namespace MatFileHandler
switch (data)
{
case MiNum _:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -446,7 +444,7 @@ namespace MatFileHandler
flags,
name);
case MiNum _:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -459,7 +457,7 @@ namespace MatFileHandler
$"This type of char array ({data.GetType()}) is not supported.");
}
case ArrayType.MxInt8:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -470,7 +468,7 @@ namespace MatFileHandler
case ArrayType.MxUInt8:
if (flags.Variable.HasFlag(Variable.IsLogical))
{
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -480,7 +478,7 @@ namespace MatFileHandler
name);
}
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -489,7 +487,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxInt16:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -498,7 +496,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxUInt16:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -507,7 +505,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxInt32:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -516,7 +514,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxUInt32:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -525,7 +523,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxInt64:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -534,7 +532,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxUInt64:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -543,7 +541,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxSingle:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
@@ -552,7 +550,7 @@ namespace MatFileHandler
flags,
name);
case ArrayType.MxDouble:
- return new DataElementWithArrayFlags(
+ return new DataElementWithMetadata(
DataElementConverter.ConvertToMatNumericalArrayOf(
flags,
dimensions,
diff --git a/MatFileHandler/DataElementWithArrayFlags.cs b/MatFileHandler/DataElementWithArrayFlags.cs
deleted file mode 100644
index ce48154..0000000
--- a/MatFileHandler/DataElementWithArrayFlags.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace MatFileHandler
-{
- internal class DataElementWithArrayFlags
- {
- public DataElementWithArrayFlags(DataElement element, ArrayFlags flags, string name, uint nzMax = 0)
- {
- Element = element;
- Flags = flags;
- Name = name;
- NzMax = nzMax;
- }
-
- public DataElementWithArrayFlags(DataElement element)
- {
- Element = element;
- Flags = default;
- Name = default;
- }
-
- public DataElement Element { get; }
-
- public ArrayFlags Flags { get; }
-
- public string Name { get; }
-
- public uint NzMax { get; }
- }
-}
\ No newline at end of file
diff --git a/MatFileHandler/DataElementWithMetadata.cs b/MatFileHandler/DataElementWithMetadata.cs
new file mode 100644
index 0000000..9ae5fc0
--- /dev/null
+++ b/MatFileHandler/DataElementWithMetadata.cs
@@ -0,0 +1,54 @@
+// Copyright 2017-2018 Alexander Luzgarev
+
+namespace MatFileHandler
+{
+ ///
+ /// Data element together with array flags, variable name, and sparse array's nzMax value.
+ ///
+ internal class DataElementWithMetadata
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Data element.
+ /// Array flags.
+ /// Variable name.
+ /// nzMax (for sparse arrays).
+ public DataElementWithMetadata(DataElement element, ArrayFlags flags, string name, uint nzMax = 0)
+ {
+ Element = element;
+ Flags = flags;
+ Name = name;
+ NzMax = nzMax;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Data element.
+ public DataElementWithMetadata(DataElement element)
+ {
+ Element = element;
+ }
+
+ ///
+ /// Gets data element.
+ ///
+ public DataElement Element { get; }
+
+ ///
+ /// Gets array flags.
+ ///
+ public ArrayFlags Flags { get; }
+
+ ///
+ /// Gets variable name.
+ ///
+ public string Name { get; }
+
+ ///
+ /// Gets nzMax (for sparse arrays).
+ ///
+ public uint NzMax { get; }
+ }
+}
\ No newline at end of file
diff --git a/MatFileHandler/DataExtraction.cs b/MatFileHandler/DataExtraction.cs
index d79ed1e..77c9e9f 100755
--- a/MatFileHandler/DataExtraction.cs
+++ b/MatFileHandler/DataExtraction.cs
@@ -363,6 +363,14 @@ namespace MatFileHandler
$"Expected data element that would be convertible to uint64, found {element.GetType()}.");
}
+ ///
+ /// Convert sparse MATLAB data into dictionary.
+ ///
+ /// Array element type.
+ /// Array of row indices.
+ /// Array of column indices.
+ /// Getter function.
+ /// Dictionary mapping (row, column) pairs to value.
public static Dictionary<(int, int), T> ConvertMatlabSparseToDictionary(
int[] rowIndex,
int[] columnIndex,
diff --git a/MatFileHandler/Hdf/Attribute.cs b/MatFileHandler/Hdf/Attribute.cs
index a72bf76..7c65265 100644
--- a/MatFileHandler/Hdf/Attribute.cs
+++ b/MatFileHandler/Hdf/Attribute.cs
@@ -1,18 +1,32 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using System.Runtime.InteropServices;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// Wrapper for HDF attribute.
+ ///
internal struct Attribute : IDisposable
{
- public long Id { get; private set; }
-
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Containing location id.
+ /// Attribute name.
public Attribute(long locationId, string name)
{
Id = H5A.open_by_name(locationId, ".", name);
}
+ ///
+ /// Gets attribute id.
+ ///
+ public long Id { get; private set; }
+
+ ///
public void Dispose()
{
if (Id != -1)
@@ -22,6 +36,28 @@ namespace MatFileHandler.Hdf
}
}
+ ///
+ /// Get HDF type of the attribute.
+ ///
+ /// HDF type.
+ public Type GetHdfType()
+ {
+ return new Type(H5A.get_type(Id));
+ }
+
+ ///
+ /// Get HDF space of the attribute.
+ ///
+ /// HDF space.
+ public Space GetSpace()
+ {
+ return new Space(H5A.get_space(Id));
+ }
+
+ ///
+ /// Read attribute value as boolean.
+ ///
+ /// Attribute value.
public bool ReadBool()
{
using (var h = new MemoryHandle(sizeof(int)))
@@ -32,19 +68,14 @@ namespace MatFileHandler.Hdf
}
}
+ ///
+ /// Read attribute value to the provided memory handle.
+ ///
+ /// Target memory handle.
+ /// HDF type to read from the attribute.
public void ReadToHandle(MemoryHandle handle, Type type)
{
H5A.read(Id, type.Id, handle.Handle);
}
-
- public Type GetHdfType()
- {
- return new Type(H5A.get_type(Id));
- }
-
- public Space GetSpace()
- {
- return new Space(H5A.get_space(Id));
- }
}
}
\ No newline at end of file
diff --git a/MatFileHandler/Hdf/Class.cs b/MatFileHandler/Hdf/Class.cs
index d735e9c..2b7ed08 100644
--- a/MatFileHandler/Hdf/Class.cs
+++ b/MatFileHandler/Hdf/Class.cs
@@ -1,23 +1,41 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// HDF class.
+ ///
internal struct Class : IEquatable
{
- public Class(H5T.class_t c)
+ ///
+ /// Compound class.
+ ///
+ public static readonly Class Compound = new Class(H5T.class_t.COMPOUND);
+
+ ///
+ /// Reference class.
+ ///
+ public static readonly Class Reference = new Class(H5T.class_t.REFERENCE);
+
+ ///
+ /// String class.
+ ///
+ public static readonly Class String = new Class(H5T.class_t.STRING);
+
+ private readonly H5T.class_t classT;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// HDF class_t.
+ public Class(H5T.class_t classT)
{
- C = c;
+ this.classT = classT;
}
- public static Class String => new Class(H5T.class_t.STRING);
-
- public static Class Reference => new Class(H5T.class_t.REFERENCE);
-
- public static Class Compound => new Class(H5T.class_t.COMPOUND);
-
- public H5T.class_t C { get; }
-
public static bool operator ==(Class one, Class other)
{
return one.Equals(other);
@@ -28,19 +46,26 @@ namespace MatFileHandler.Hdf
return !one.Equals(other);
}
+ ///
+ /// Check if the class is equal to the other class.
+ ///
+ /// Other class.
+ /// True iff the classes are equal.
public bool Equals(Class other)
{
- return C == other.C;
+ return classT == other.classT;
}
+ ///
public override bool Equals(object obj)
{
return obj is Class other && Equals(other);
}
+ ///
public override int GetHashCode()
{
- return (int)C;
+ return (int)classT;
}
}
}
\ No newline at end of file
diff --git a/MatFileHandler/Hdf/Dataset.cs b/MatFileHandler/Hdf/Dataset.cs
index fcc4cca..c0aaf82 100644
--- a/MatFileHandler/Hdf/Dataset.cs
+++ b/MatFileHandler/Hdf/Dataset.cs
@@ -1,22 +1,50 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// HDF dataset.
+ ///
internal struct Dataset : IDisposable
{
- public long Id { get; private set; }
-
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Dataset id.
public Dataset(long datasetId)
{
Id = datasetId;
}
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Containing group id.
+ /// Name of the dataset in the group.
public Dataset(long groupId, string name)
{
Id = H5D.open(groupId, name);
}
+ ///
+ /// Gets dataset id.
+ ///
+ public long Id { get; private set; }
+
+ ///
+ /// Check if dataset attribute with the given name exists.
+ ///
+ /// Attribute name.
+ /// True iff dataset has an attribute with this name.
+ public bool AttributeExists(string name)
+ {
+ return H5A.exists_by_name(Id, ".", name) != 0;
+ }
+
+ ///
public void Dispose()
{
if (Id != -1)
@@ -26,31 +54,48 @@ namespace MatFileHandler.Hdf
}
}
+ ///
+ /// Open attribute with given name.
+ ///
+ /// Attribute name.
+ /// Attribute.
public Attribute GetAttribute(string name)
{
return new Attribute(Id, name);
}
- public bool AttributeExists(string name)
- {
- return H5A.exists_by_name(Id, ".", name) != 0;
- }
-
- public Type GetHdfType()
- {
- return new Type(H5D.get_type(Id));
- }
-
- public int GetStorageSize()
- {
- return (int)H5D.get_storage_size(Id);
- }
-
+ ///
+ /// Get HDF space of the dataset.
+ ///
+ /// HDF space.
public Space GetHdfSpace()
{
return new Space(H5D.get_space(Id));
}
+ ///
+ /// Get HDF type of the dataset.
+ ///
+ /// HDF type.
+ public Type GetHdfType()
+ {
+ return new Type(H5D.get_type(Id));
+ }
+
+ ///
+ /// Get storage size of the dataset.
+ ///
+ /// Storage size.
+ public int GetStorageSize()
+ {
+ return (int)H5D.get_storage_size(Id);
+ }
+
+ ///
+ /// Read the contents of the dataset into the memory handle.
+ ///
+ /// HDF type of the data to read.
+ /// Memory handle.
public void ReadToHandle(Type type, MemoryHandle handle)
{
H5D.read(Id, type.Id, H5S.ALL, H5S.ALL, H5P.DEFAULT, handle.Handle);
diff --git a/MatFileHandler/Hdf/Group.cs b/MatFileHandler/Hdf/Group.cs
index 3812a1e..20b4161 100644
--- a/MatFileHandler/Hdf/Group.cs
+++ b/MatFileHandler/Hdf/Group.cs
@@ -1,17 +1,41 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// Hdf group.
+ ///
internal struct Group : IDisposable
{
- public long Id { get; private set; }
-
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Containing group id.
+ /// Name of the subgroup in the containing group.
public Group(long groupId, string name)
{
Id = H5G.open(groupId, name);
}
+ ///
+ /// Gets group id.
+ ///
+ public long Id { get; private set; }
+
+ ///
+ /// Check if group attribute with the given name exists.
+ ///
+ /// Attribute name.
+ /// True iff group has an attribute with this name.
+ public bool AttributeExists(string name)
+ {
+ return H5A.exists_by_name(Id, ".", name) != 0;
+ }
+
+ ///
public void Dispose()
{
if (Id != -1)
@@ -21,14 +45,14 @@ namespace MatFileHandler.Hdf
}
}
+ ///
+ /// Get group attribute.
+ ///
+ /// Attribute name.
+ /// Attribute.
public Attribute GetAttribute(string name)
{
return new Attribute(Id, name);
}
-
- public bool AttributeExists(string name)
- {
- return H5A.exists_by_name(Id, ".", name) != 0;
- }
}
}
\ No newline at end of file
diff --git a/MatFileHandler/Hdf/MatlabClass.cs b/MatFileHandler/Hdf/MatlabClass.cs
index b522fdd..4309b17 100644
--- a/MatFileHandler/Hdf/MatlabClass.cs
+++ b/MatFileHandler/Hdf/MatlabClass.cs
@@ -1,20 +1,80 @@
-namespace MatFileHandler.Hdf
+// Copyright 2017-2018 Alexander Luzgarev
+
+namespace MatFileHandler.Hdf
{
+ ///
+ /// Matlab classes as they appear in HDF files.
+ ///
internal enum MatlabClass
{
+ ///
+ /// Empty array.
+ ///
MEmpty,
+
+ ///
+ /// Char array.
+ ///
MChar,
+
+ ///
+ /// Int8 array.
+ ///
MInt8,
+
+ ///
+ /// UInt8 array.
+ ///
MUInt8,
+
+ ///
+ /// Int16 array.
+ ///
MInt16,
+
+ ///
+ /// UInt16 array.
+ ///
MUInt16,
+
+ ///
+ /// Int32 array.
+ ///
MInt32,
+
+ ///
+ /// UInt32 array.
+ ///
MUInt32,
+
+ ///
+ /// Int64 array.
+ ///
MInt64,
+
+ ///
+ /// UInt64 array.
+ ///
MUInt64,
+
+ ///
+ /// Single-precision floating point array.
+ ///
MSingle,
+
+ ///
+ /// Double-precision floating point array.
+ ///
MDouble,
+
+ ///
+ /// Cell array.
+ ///
MCell,
+
+ ///
+ /// Logical array.
+ ///
MLogical,
}
}
\ No newline at end of file
diff --git a/MatFileHandler/Hdf/MemoryHandle.cs b/MatFileHandler/Hdf/MemoryHandle.cs
index 0aac738..b5d4ae6 100644
--- a/MatFileHandler/Hdf/MemoryHandle.cs
+++ b/MatFileHandler/Hdf/MemoryHandle.cs
@@ -1,15 +1,27 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using System.Runtime.InteropServices;
namespace MatFileHandler.Hdf
{
+ ///
+ /// Wrapper around IntPtr to array in unmanaged memory.
+ ///
internal sealed class MemoryHandle : IDisposable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Size of the memory to be allocated.
internal MemoryHandle(int sizeInBytes)
{
Handle = Marshal.AllocHGlobal(sizeInBytes);
}
+ ///
+ /// Gets wrapped IntPtr.
+ ///
internal IntPtr Handle { get; private set; }
///
diff --git a/MatFileHandler/Hdf/ReferenceArray.cs b/MatFileHandler/Hdf/ReferenceArray.cs
index adfcbeb..c395de7 100644
--- a/MatFileHandler/Hdf/ReferenceArray.cs
+++ b/MatFileHandler/Hdf/ReferenceArray.cs
@@ -1,32 +1,35 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
-using System.Text;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// Array of HDF references stored in an HDF dataset.
+ ///
internal struct ReferenceArray : IDisposable, IEnumerable
{
- public Dataset Dataset { get; }
-
- public int Size { get; }
-
- public MemoryHandle Buf { get; }
-
- public Dataset[] References { get; }
+ private readonly Dataset[] references;
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Containing dataset.
+ /// Array size.
public ReferenceArray(Dataset dataset, int size)
{
Dataset = dataset;
Size = size;
Buf = new MemoryHandle(Marshal.SizeOf(default(IntPtr)) * size);
Dataset.ReadToHandle(Type.Reference, Buf);
- References = new Dataset[size];
+ references = new Dataset[size];
for (var i = 0; i < size; i++)
{
- References[i] =
+ references[i] =
new Dataset(H5R.dereference(
dataset.Id,
H5P.DEFAULT,
@@ -35,26 +38,48 @@ namespace MatFileHandler.Hdf
}
}
+ ///
+ /// Gets containing dataset.
+ ///
+ public Dataset Dataset { get; }
+
+ ///
+ /// Gets references.
+ ///
+ public IReadOnlyList References => references;
+
+ ///
+ /// Gets array size.
+ ///
+ public int Size { get; }
+
+ private MemoryHandle Buf { get; }
+
+ ///
public void Dispose()
{
Buf?.Dispose();
- if (!(References is null))
+ if (References is null)
{
- foreach (var reference in References)
- {
- reference.Dispose();
- }
+ return;
+ }
+
+ foreach (var reference in References)
+ {
+ reference.Dispose();
}
}
+ ///
public IEnumerator GetEnumerator()
{
return ((IEnumerable)References).GetEnumerator();
}
+ ///
IEnumerator IEnumerable.GetEnumerator()
{
return References.GetEnumerator();
}
}
-}
+}
\ No newline at end of file
diff --git a/MatFileHandler/Hdf/Space.cs b/MatFileHandler/Hdf/Space.cs
index 87751e4..c2821a1 100644
--- a/MatFileHandler/Hdf/Space.cs
+++ b/MatFileHandler/Hdf/Space.cs
@@ -1,22 +1,42 @@
-using System.Linq;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System.Linq;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// HDF space.
+ ///
internal struct Space
{
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Space id.
public Space(long id)
{
Id = id;
}
+ ///
+ /// Gets space id.
+ ///
public long Id { get; }
+ ///
+ /// Get space rank.
+ ///
+ /// Space rank.
public int GetRank()
{
return H5S.get_simple_extent_ndims(Id);
}
+ ///
+ /// Get dimensions of the space.
+ ///
+ /// Space dimensions.
public int[] GetDimensions()
{
var dims = new ulong[GetRank()];
diff --git a/MatFileHandler/Hdf/Type.cs b/MatFileHandler/Hdf/Type.cs
index 8a36d7c..4558d01 100644
--- a/MatFileHandler/Hdf/Type.cs
+++ b/MatFileHandler/Hdf/Type.cs
@@ -1,70 +1,147 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using HDF.PInvoke;
namespace MatFileHandler.Hdf
{
+ ///
+ /// HDF type.
+ ///
internal struct Type
{
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Type id.
public Type(long id)
{
Id = id;
}
+ ///
+ /// Gets HDF string type.
+ ///
+ public static Type CS1 => new Type(H5T.C_S1);
+
+ ///
+ /// Gets HDF double type.
+ ///
+ public static Type NativeDouble => new Type(H5T.NATIVE_DOUBLE);
+
+ ///
+ /// Gets HDF float (single) type.
+ ///
+ public static Type NativeFloat => new Type(H5T.NATIVE_FLOAT);
+
+ ///
+ /// Gets HDF int type.
+ ///
+ public static Type NativeInt => new Type(H5T.NATIVE_INT);
+
+ ///
+ /// Gets HDF int16 type.
+ ///
+ public static Type NativeInt16 => new Type(H5T.NATIVE_INT16);
+
+ ///
+ /// Gets HDF int32 type.
+ ///
+ public static Type NativeInt32 => new Type(H5T.NATIVE_INT32);
+
+ ///
+ /// Gets HDF int64 type.
+ ///
+ public static Type NativeInt64 => new Type(H5T.NATIVE_INT64);
+
+ ///
+ /// Gets HDF int8 type.
+ ///
+ public static Type NativeInt8 => new Type(H5T.NATIVE_INT8);
+
+ ///
+ /// Gets HDF uint type.
+ ///
+ public static Type NativeUInt => new Type(H5T.NATIVE_UINT);
+
+ ///
+ /// Gets HDF uint16 type
+ ///
+ public static Type NativeUInt16 => new Type(H5T.NATIVE_UINT16);
+
+ ///
+ /// Gets HDF uint32 type.
+ ///
+ public static Type NativeUInt32 => new Type(H5T.NATIVE_UINT32);
+
+ ///
+ /// Gets HDF uint64 type.
+ ///
+ public static Type NativeUInt64 => new Type(H5T.NATIVE_UINT64);
+
+ ///
+ /// Gets HDF uint8 type.
+ ///
+ public static Type NativeUInt8 => new Type(H5T.NATIVE_UINT8);
+
+ ///
+ /// Gets HDF reference type.
+ ///
+ public static Type Reference => new Type(H5T.STD_REF_OBJ);
+
+ ///
+ /// Gets type id.
+ ///
public long Id { get; }
+ ///
+ /// Create compound type of given size.
+ ///
+ /// Size of the type.
+ /// The created type.
+ public static Type CreateCompound(int size)
+ {
+ return new Type(H5T.create(H5T.class_t.COMPOUND, (IntPtr)size));
+ }
+
+ ///
+ /// Get class of the type.
+ ///
+ /// Class of the type.
public Class GetClass()
{
return new Class(H5T.get_class(Id));
}
+ ///
+ /// Get size of the type.
+ ///
+ /// Size of the type.
public int GetSize()
{
return (int)H5T.get_size(Id);
}
- public static Type NativeInt8 => new Type(H5T.NATIVE_INT8);
-
- public static Type NativeUInt8 => new Type(H5T.NATIVE_UINT8);
-
- public static Type NativeInt16 => new Type(H5T.NATIVE_INT16);
-
- public static Type NativeUInt16 => new Type(H5T.NATIVE_UINT16);
-
- public static Type NativeInt32 => new Type(H5T.NATIVE_INT32);
-
- public static Type NativeUInt32 => new Type(H5T.NATIVE_UINT32);
-
- public static Type NativeInt64 => new Type(H5T.NATIVE_INT64);
-
- public static Type NativeUInt64 => new Type(H5T.NATIVE_UINT64);
-
- public static Type NativeFloat => new Type(H5T.NATIVE_FLOAT);
-
- public static Type NativeDouble => new Type(H5T.NATIVE_DOUBLE);
-
- public static Type NativeInt => new Type(H5T.NATIVE_INT);
-
- public static Type NativeUInt => new Type(H5T.NATIVE_UINT);
-
- public static Type CS1 => new Type(H5T.C_S1);
-
- public static Type Reference => new Type(H5T.STD_REF_OBJ);
+ ///
+ /// Insert a field into the type.
+ ///
+ /// Field name.
+ /// Field type.
+ public void InsertField(string name, Type fieldType)
+ {
+ H5T.insert(Id, name, IntPtr.Zero, fieldType.Id);
+ }
+ ///
+ /// Create type copy with same class and given size.
+ ///
+ /// New size.
+ /// New type.
public Type WithSize(int size)
{
var classId = H5T.copy(Id);
H5T.set_size(classId, (IntPtr)size);
return new Type(classId);
}
-
- public static Type CreateCompound(int size)
- {
- return new Type(H5T.create(H5T.class_t.COMPOUND, (IntPtr)size));
- }
-
- public void InsertField(string name, Type fieldType)
- {
- H5T.insert(Id, name, IntPtr.Zero, fieldType.Id);
- }
}
}
\ No newline at end of file
diff --git a/MatFileHandler/HdfFileReader.cs b/MatFileHandler/HdfFileReader.cs
index 312bb41..ac4b754 100644
--- a/MatFileHandler/HdfFileReader.cs
+++ b/MatFileHandler/HdfFileReader.cs
@@ -1,4 +1,6 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
@@ -9,29 +11,40 @@ using MatFileHandler.Hdf;
namespace MatFileHandler
{
+ ///
+ /// Reader of HDF files containing MATLAB data.
+ ///
internal class HdfFileReader
{
- private const string classAttributeName = "MATLAB_class";
+ private const string ClassAttributeName = "MATLAB_class";
- private const string globalAttributeName = "MATLAB_global";
+ private const string GlobalAttributeName = "MATLAB_global";
- private const string sparseAttributeName = "MATLAB_sparse";
- private long fileId;
+ private const string SparseAttributeName = "MATLAB_sparse";
+
+ private readonly long fileId;
private List variables;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// File id to read data from.
internal HdfFileReader(long fileId)
{
this.fileId = fileId;
}
+ ///
+ /// Read MATLAB data from the HDF file.
+ ///
+ /// MATLAB data file contents.
internal IMatFile Read()
{
variables = new List();
var group_info = default(H5G.info_t);
H5G.get_info(fileId, ref group_info);
var numberOfVariables = group_info.nlinks;
-
ulong idx = 0;
while (idx < numberOfVariables)
{
@@ -117,12 +130,22 @@ namespace MatFileHandler
Marshal.Copy(buf.Handle, matlabClassNameBytes, 0, typeIdSize);
}
- return Encoding.ASCII.GetString(matlabClassNameBytes);
+ var length = typeIdSize;
+ for (var i = 0; i < typeIdSize; i++)
+ {
+ if (matlabClassNameBytes[i] == 0)
+ {
+ length = i;
+ break;
+ }
+ }
+
+ return Encoding.ASCII.GetString(matlabClassNameBytes, 0, length);
}
private static string GetMatlabClassOfDataset(Dataset dataset)
{
- using (var attribute = dataset.GetAttribute(classAttributeName))
+ using (var attribute = dataset.GetAttribute(ClassAttributeName))
{
return GetMatlabClassFromAttribute(attribute);
}
@@ -130,7 +153,7 @@ namespace MatFileHandler
private static string GetMatlabClassOfGroup(Group group)
{
- using (var attribute = group.GetAttribute(classAttributeName))
+ using (var attribute = group.GetAttribute(ClassAttributeName))
{
return GetMatlabClassFromAttribute(attribute);
}
@@ -315,9 +338,8 @@ namespace MatFileHandler
return ReadStruct(group.Id);
}
- if (group.AttributeExists(sparseAttributeName))
+ if (group.AttributeExists(SparseAttributeName))
{
- var dims = new int[0];
var arrayType = ArrayTypeFromMatlabClassName(matlabClass);
switch (arrayType)
@@ -378,7 +400,6 @@ namespace MatFileHandler
{
var numberOfElements = dims.NumberOfElements();
var dataSize = numberOfElements * SizeOfArrayElement(arrayType);
- var storageSize = dataset.GetStorageSize();
var dataSetType = dataset.GetHdfType();
var dataSetTypeClass = dataSetType.GetClass();
var isCompound = dataSetTypeClass == Class.Compound;
@@ -405,11 +426,6 @@ namespace MatFileHandler
}
}
- if (dataSize != storageSize)
- {
- throw new Exception("Data size mismatch.");
- }
-
var data = ReadDataset(dataset, H5tTypeFromHdfMatlabClass(arrayType), dataSize);
var convertedData = ConvertDataToProperType(data, arrayType);
return new MatNumericalArrayOf(dims, convertedData);
@@ -418,7 +434,7 @@ namespace MatFileHandler
private static IArray ReadSparseArray(long groupId, MatlabClass arrayType)
where T : struct
{
- using (var sparseAttribute = new Hdf.Attribute(groupId, sparseAttributeName))
+ using (var sparseAttribute = new Hdf.Attribute(groupId, SparseAttributeName))
{
using (var numberOfRowsHandle = new MemoryHandle(sizeof(uint)))
{
@@ -464,7 +480,7 @@ namespace MatFileHandler
var complexData =
CombineComplexData(
convertedRealData as double[],
- convertedImaginaryData as double[])
+ convertedImaginaryData as double[])
.ToArray();
var complexDataDictionary =
DataExtraction.ConvertMatlabSparseToDictionary(
@@ -475,7 +491,7 @@ namespace MatFileHandler
}
else
{
- var complexData =
+ var complexData =
CombineComplexOfData(
convertedRealData,
convertedImaginaryData)
@@ -489,11 +505,6 @@ namespace MatFileHandler
}
}
- if (dataSize != storageSize)
- {
- throw new Exception("Data size mismatch.");
- }
-
var d = ReadDataset(data, H5tTypeFromHdfMatlabClass(arrayType), dataSize);
var elements = ConvertDataToProperType(d, arrayType);
var dataDictionary =
@@ -515,7 +526,7 @@ namespace MatFileHandler
var firstFieldType = firstField.GetHdfType();
if (firstFieldType.GetClass() == Class.Reference)
{
- if (firstField.AttributeExists(classAttributeName))
+ if (firstField.AttributeExists(ClassAttributeName))
{
throw new NotImplementedException();
}
@@ -592,12 +603,12 @@ namespace MatFileHandler
private bool ReadGlobalFlag(Group group)
{
- if (!group.AttributeExists(globalAttributeName))
+ if (!group.AttributeExists(GlobalAttributeName))
{
return false;
}
- using (var globalAttribute = group.GetAttribute(globalAttributeName))
+ using (var globalAttribute = group.GetAttribute(GlobalAttributeName))
{
return globalAttribute.ReadBool();
}
@@ -605,12 +616,12 @@ namespace MatFileHandler
private bool ReadGlobalFlag(Dataset dataset)
{
- if (!dataset.AttributeExists(globalAttributeName))
+ if (!dataset.AttributeExists(GlobalAttributeName))
{
return false;
}
- using (var globalAttribute = dataset.GetAttribute(globalAttributeName))
+ using (var globalAttribute = dataset.GetAttribute(GlobalAttributeName))
{
return globalAttribute.ReadBool();
}
diff --git a/MatFileHandler/Header.cs b/MatFileHandler/Header.cs
index 0e7db2b..d63fb64 100755
--- a/MatFileHandler/Header.cs
+++ b/MatFileHandler/Header.cs
@@ -21,6 +21,9 @@ namespace MatFileHandler
Version = version;
}
+ ///
+ /// Gets raw byte contents of the header.
+ ///
public byte[] RawBytes { get; }
///
diff --git a/MatFileHandler/MatFileHdfReader.cs b/MatFileHandler/MatFileHdfReader.cs
index 8b6642c..2cbe907 100644
--- a/MatFileHandler/MatFileHdfReader.cs
+++ b/MatFileHandler/MatFileHdfReader.cs
@@ -1,12 +1,23 @@
-using System;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
using System.IO;
using System.Runtime.InteropServices;
using HDF.PInvoke;
namespace MatFileHandler
{
+ ///
+ /// Reader for MATLAB HDF (-v7.3) files.
+ ///
internal static class MatFileHdfReader
{
+ ///
+ /// Continue reading MATLAB HDF file after reading the MATLAB header.
+ ///
+ /// MATLAB header that was read.
+ /// Stream to read the rest of the file from.
+ /// MATLAB data file contents.
internal static IMatFile ContinueReadingHdfFile(Header header, Stream stream)
{
using (var memoryStream = new MemoryStream())
diff --git a/MatFileHandler/MatFileLevel5Reader.cs b/MatFileHandler/MatFileLevel5Reader.cs
index 5a70629..e6c9f95 100644
--- a/MatFileHandler/MatFileLevel5Reader.cs
+++ b/MatFileHandler/MatFileLevel5Reader.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System.Collections.Generic;
using System.IO;
namespace MatFileHandler
@@ -61,6 +63,12 @@ namespace MatFileHandler
return ReadRawVariables(reader, subsystemDataOffset, subsystemData);
}
+ ///
+ /// Continue reading old-style (Level 5) MATLAB file.
+ ///
+ /// Header that was already read.
+ /// Reader for reading the rest of the file.
+ /// MATLAB data file contents.
internal static IMatFile ContinueReadingLevel5File(Header header, BinaryReader reader)
{
var rawVariables = ReadRawVariables(reader, header.SubsystemDataOffset);
diff --git a/MatFileHandler/MatFileReader.cs b/MatFileHandler/MatFileReader.cs
index 1b79b3b..a12c09a 100755
--- a/MatFileHandler/MatFileReader.cs
+++ b/MatFileHandler/MatFileReader.cs
@@ -33,6 +33,11 @@ namespace MatFileHandler
}
}
+ private static Header ReadHeader(BinaryReader reader)
+ {
+ return Header.Read(reader);
+ }
+
private IMatFile Read(BinaryReader reader)
{
var header = ReadHeader(reader);
@@ -46,10 +51,5 @@ namespace MatFileHandler
throw new NotSupportedException($"Unknown file format.");
}
}
-
- private static Header ReadHeader(BinaryReader reader)
- {
- return Header.Read(reader);
- }
}
}
\ No newline at end of file
diff --git a/MatFileHandler/MatSparseArrayOf.cs b/MatFileHandler/MatSparseArrayOf.cs
index fd11039..a79b290 100755
--- a/MatFileHandler/MatSparseArrayOf.cs
+++ b/MatFileHandler/MatSparseArrayOf.cs
@@ -43,7 +43,7 @@ namespace MatFileHandler
get
{
var rowAndColumn = GetRowAndColumn(list);
- return DataDictionary.ContainsKey(rowAndColumn) ? DataDictionary[rowAndColumn] : default(T);
+ return DataDictionary.ContainsKey(rowAndColumn) ? DataDictionary[rowAndColumn] : default;
}
set => DataDictionary[GetRowAndColumn(list)] = value;
}
diff --git a/MatFileHandler/RawVariable.cs b/MatFileHandler/RawVariable.cs
index b37008d..0576f11 100644
--- a/MatFileHandler/RawVariable.cs
+++ b/MatFileHandler/RawVariable.cs
@@ -17,6 +17,8 @@ namespace MatFileHandler
///
/// Offset of the variable in the source file.
/// Data element parsed from the file.
+ /// Array flags.
+ /// Variable name.
internal RawVariable(long offset, DataElement dataElement, ArrayFlags flags, string name)
{
Offset = offset;
@@ -30,8 +32,14 @@ namespace MatFileHandler
///
public DataElement DataElement { get; }
+ ///
+ /// Gets array flags.
+ ///
public ArrayFlags Flags { get; }
+ ///
+ /// Gets variable name.
+ ///
public string Name { get; }
///