Add XML documentation
This commit is contained in:
parent
bdd04a80b7
commit
e6d236139c
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests of file reading API (HDF cases).
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class MatFileReaderHdfTests
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ using NUnit.Framework;
|
||||
namespace MatFileHandler.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests of file reading API.
|
||||
/// Tests of file reading API (Level 5 cases).
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class MatFileReaderLevel5Tests
|
||||
|
@ -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<sbyte>(tag, reader);
|
||||
case DataType.MiUInt8:
|
||||
case DataType.MiUtf8:
|
||||
return ReadNum<byte>(tag, reader);
|
||||
case DataType.MiInt16:
|
||||
return ReadNum<short>(tag, reader);
|
||||
case DataType.MiUInt16:
|
||||
case DataType.MiUtf16:
|
||||
return ReadNum<ushort>(tag, reader);
|
||||
case DataType.MiInt32:
|
||||
return ReadNum<int>(tag, reader);
|
||||
case DataType.MiUInt32:
|
||||
return ReadNum<uint>(tag, reader);
|
||||
case DataType.MiSingle:
|
||||
return ReadNum<float>(tag, reader);
|
||||
case DataType.MiDouble:
|
||||
return ReadNum<double>(tag, reader);
|
||||
case DataType.MiInt64:
|
||||
return ReadNum<long>(tag, reader);
|
||||
case DataType.MiUInt64:
|
||||
return ReadNum<ulong>(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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a data element.
|
||||
/// </summary>
|
||||
/// <param name="reader">Input reader.</param>
|
||||
/// <returns>Data element.</returns>
|
||||
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<IArray>();
|
||||
@ -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<sbyte> ??
|
||||
throw new HandlerException("Unexpected type in object name.");
|
||||
@ -242,7 +195,7 @@ namespace MatFileHandler
|
||||
if (data is MatNumericalArrayOf<uint> 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<bool>(
|
||||
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<double> _:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatSparseArrayOf<double>(
|
||||
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<sbyte>(tag, reader);
|
||||
case DataType.MiUInt8:
|
||||
case DataType.MiUtf8:
|
||||
return ReadNum<byte>(tag, reader);
|
||||
case DataType.MiInt16:
|
||||
return ReadNum<short>(tag, reader);
|
||||
case DataType.MiUInt16:
|
||||
case DataType.MiUtf16:
|
||||
return ReadNum<ushort>(tag, reader);
|
||||
case DataType.MiInt32:
|
||||
return ReadNum<int>(tag, reader);
|
||||
case DataType.MiUInt32:
|
||||
return ReadNum<uint>(tag, reader);
|
||||
case DataType.MiSingle:
|
||||
return ReadNum<float>(tag, reader);
|
||||
case DataType.MiDouble:
|
||||
return ReadNum<double>(tag, reader);
|
||||
case DataType.MiInt64:
|
||||
return ReadNum<long>(tag, reader);
|
||||
case DataType.MiUInt64:
|
||||
return ReadNum<ulong>(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<int> ??
|
||||
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<byte> _:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<byte>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -446,7 +444,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case MiNum<ushort> _:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<ushort>(
|
||||
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<sbyte>(
|
||||
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<bool>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -480,7 +478,7 @@ namespace MatFileHandler
|
||||
name);
|
||||
}
|
||||
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<byte>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -489,7 +487,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxInt16:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<short>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -498,7 +496,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxUInt16:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<ushort>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -507,7 +505,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxInt32:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<int>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -516,7 +514,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxUInt32:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<uint>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -525,7 +523,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxInt64:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<long>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -534,7 +532,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxUInt64:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<ulong>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -543,7 +541,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxSingle:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<float>(
|
||||
flags,
|
||||
dimensions,
|
||||
@ -552,7 +550,7 @@ namespace MatFileHandler
|
||||
flags,
|
||||
name);
|
||||
case ArrayType.MxDouble:
|
||||
return new DataElementWithArrayFlags(
|
||||
return new DataElementWithMetadata(
|
||||
DataElementConverter.ConvertToMatNumericalArrayOf<double>(
|
||||
flags,
|
||||
dimensions,
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
54
MatFileHandler/DataElementWithMetadata.cs
Normal file
54
MatFileHandler/DataElementWithMetadata.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
namespace MatFileHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Data element together with array flags, variable name, and sparse array's nzMax value.
|
||||
/// </summary>
|
||||
internal class DataElementWithMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataElementWithMetadata"/> class.
|
||||
/// </summary>
|
||||
/// <param name="element">Data element.</param>
|
||||
/// <param name="flags">Array flags.</param>
|
||||
/// <param name="name">Variable name.</param>
|
||||
/// <param name="nzMax">nzMax (for sparse arrays).</param>
|
||||
public DataElementWithMetadata(DataElement element, ArrayFlags flags, string name, uint nzMax = 0)
|
||||
{
|
||||
Element = element;
|
||||
Flags = flags;
|
||||
Name = name;
|
||||
NzMax = nzMax;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataElementWithMetadata"/> class.
|
||||
/// </summary>
|
||||
/// <param name="element">Data element.</param>
|
||||
public DataElementWithMetadata(DataElement element)
|
||||
{
|
||||
Element = element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets data element.
|
||||
/// </summary>
|
||||
public DataElement Element { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets array flags.
|
||||
/// </summary>
|
||||
public ArrayFlags Flags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets variable name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets nzMax (for sparse arrays).
|
||||
/// </summary>
|
||||
public uint NzMax { get; }
|
||||
}
|
||||
}
|
@ -363,6 +363,14 @@ namespace MatFileHandler
|
||||
$"Expected data element that would be convertible to uint64, found {element.GetType()}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert sparse MATLAB data into dictionary.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Array element type.</typeparam>
|
||||
/// <param name="rowIndex">Array of row indices.</param>
|
||||
/// <param name="columnIndex">Array of column indices.</param>
|
||||
/// <param name="get">Getter function.</param>
|
||||
/// <returns>Dictionary mapping (row, column) pairs to value.</returns>
|
||||
public static Dictionary<(int, int), T> ConvertMatlabSparseToDictionary<T>(
|
||||
int[] rowIndex,
|
||||
int[] columnIndex,
|
||||
|
@ -1,18 +1,32 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper for HDF attribute.
|
||||
/// </summary>
|
||||
internal struct Attribute : IDisposable
|
||||
{
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Attribute"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="locationId">Containing location id.</param>
|
||||
/// <param name="name">Attribute name.</param>
|
||||
public Attribute(long locationId, string name)
|
||||
{
|
||||
Id = H5A.open_by_name(locationId, ".", name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets attribute id.
|
||||
/// </summary>
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (Id != -1)
|
||||
@ -22,6 +36,28 @@ namespace MatFileHandler.Hdf
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get HDF type of the attribute.
|
||||
/// </summary>
|
||||
/// <returns>HDF type.</returns>
|
||||
public Type GetHdfType()
|
||||
{
|
||||
return new Type(H5A.get_type(Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get HDF space of the attribute.
|
||||
/// </summary>
|
||||
/// <returns>HDF space.</returns>
|
||||
public Space GetSpace()
|
||||
{
|
||||
return new Space(H5A.get_space(Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read attribute value as boolean.
|
||||
/// </summary>
|
||||
/// <returns>Attribute value.</returns>
|
||||
public bool ReadBool()
|
||||
{
|
||||
using (var h = new MemoryHandle(sizeof(int)))
|
||||
@ -32,19 +68,14 @@ namespace MatFileHandler.Hdf
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read attribute value to the provided memory handle.
|
||||
/// </summary>
|
||||
/// <param name="handle">Target memory handle.</param>
|
||||
/// <param name="type">HDF type to read from the attribute.</param>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +1,41 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// HDF class.
|
||||
/// </summary>
|
||||
internal struct Class : IEquatable<Class>
|
||||
{
|
||||
public Class(H5T.class_t c)
|
||||
/// <summary>
|
||||
/// Compound class.
|
||||
/// </summary>
|
||||
public static readonly Class Compound = new Class(H5T.class_t.COMPOUND);
|
||||
|
||||
/// <summary>
|
||||
/// Reference class.
|
||||
/// </summary>
|
||||
public static readonly Class Reference = new Class(H5T.class_t.REFERENCE);
|
||||
|
||||
/// <summary>
|
||||
/// String class.
|
||||
/// </summary>
|
||||
public static readonly Class String = new Class(H5T.class_t.STRING);
|
||||
|
||||
private readonly H5T.class_t classT;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Class"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="classT">HDF class_t.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the class is equal to the other class.
|
||||
/// </summary>
|
||||
/// <param name="other">Other class.</param>
|
||||
/// <returns>True iff the classes are equal.</returns>
|
||||
public bool Equals(Class other)
|
||||
{
|
||||
return C == other.C;
|
||||
return classT == other.classT;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is Class other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)C;
|
||||
return (int)classT;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +1,50 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// HDF dataset.
|
||||
/// </summary>
|
||||
internal struct Dataset : IDisposable
|
||||
{
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dataset"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="datasetId">Dataset id.</param>
|
||||
public Dataset(long datasetId)
|
||||
{
|
||||
Id = datasetId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dataset"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="groupId">Containing group id.</param>
|
||||
/// <param name="name">Name of the dataset in the group.</param>
|
||||
public Dataset(long groupId, string name)
|
||||
{
|
||||
Id = H5D.open(groupId, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets dataset id.
|
||||
/// </summary>
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Check if dataset attribute with the given name exists.
|
||||
/// </summary>
|
||||
/// <param name="name">Attribute name.</param>
|
||||
/// <returns>True iff dataset has an attribute with this name.</returns>
|
||||
public bool AttributeExists(string name)
|
||||
{
|
||||
return H5A.exists_by_name(Id, ".", name) != 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (Id != -1)
|
||||
@ -26,31 +54,48 @@ namespace MatFileHandler.Hdf
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open attribute with given name.
|
||||
/// </summary>
|
||||
/// <param name="name">Attribute name.</param>
|
||||
/// <returns>Attribute.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get HDF space of the dataset.
|
||||
/// </summary>
|
||||
/// <returns>HDF space.</returns>
|
||||
public Space GetHdfSpace()
|
||||
{
|
||||
return new Space(H5D.get_space(Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get HDF type of the dataset.
|
||||
/// </summary>
|
||||
/// <returns>HDF type.</returns>
|
||||
public Type GetHdfType()
|
||||
{
|
||||
return new Type(H5D.get_type(Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get storage size of the dataset.
|
||||
/// </summary>
|
||||
/// <returns>Storage size.</returns>
|
||||
public int GetStorageSize()
|
||||
{
|
||||
return (int)H5D.get_storage_size(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the contents of the dataset into the memory handle.
|
||||
/// </summary>
|
||||
/// <param name="type">HDF type of the data to read.</param>
|
||||
/// <param name="handle">Memory handle.</param>
|
||||
public void ReadToHandle(Type type, MemoryHandle handle)
|
||||
{
|
||||
H5D.read(Id, type.Id, H5S.ALL, H5S.ALL, H5P.DEFAULT, handle.Handle);
|
||||
|
@ -1,17 +1,41 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Hdf group.
|
||||
/// </summary>
|
||||
internal struct Group : IDisposable
|
||||
{
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Group"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="groupId">Containing group id.</param>
|
||||
/// <param name="name">Name of the subgroup in the containing group.</param>
|
||||
public Group(long groupId, string name)
|
||||
{
|
||||
Id = H5G.open(groupId, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets group id.
|
||||
/// </summary>
|
||||
public long Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Check if group attribute with the given name exists.
|
||||
/// </summary>
|
||||
/// <param name="name">Attribute name.</param>
|
||||
/// <returns>True iff group has an attribute with this name.</returns>
|
||||
public bool AttributeExists(string name)
|
||||
{
|
||||
return H5A.exists_by_name(Id, ".", name) != 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (Id != -1)
|
||||
@ -21,14 +45,14 @@ namespace MatFileHandler.Hdf
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get group attribute.
|
||||
/// </summary>
|
||||
/// <param name="name">Attribute name.</param>
|
||||
/// <returns>Attribute.</returns>
|
||||
public Attribute GetAttribute(string name)
|
||||
{
|
||||
return new Attribute(Id, name);
|
||||
}
|
||||
|
||||
public bool AttributeExists(string name)
|
||||
{
|
||||
return H5A.exists_by_name(Id, ".", name) != 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +1,80 @@
|
||||
namespace MatFileHandler.Hdf
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Matlab classes as they appear in HDF files.
|
||||
/// </summary>
|
||||
internal enum MatlabClass
|
||||
{
|
||||
/// <summary>
|
||||
/// Empty array.
|
||||
/// </summary>
|
||||
MEmpty,
|
||||
|
||||
/// <summary>
|
||||
/// Char array.
|
||||
/// </summary>
|
||||
MChar,
|
||||
|
||||
/// <summary>
|
||||
/// Int8 array.
|
||||
/// </summary>
|
||||
MInt8,
|
||||
|
||||
/// <summary>
|
||||
/// UInt8 array.
|
||||
/// </summary>
|
||||
MUInt8,
|
||||
|
||||
/// <summary>
|
||||
/// Int16 array.
|
||||
/// </summary>
|
||||
MInt16,
|
||||
|
||||
/// <summary>
|
||||
/// UInt16 array.
|
||||
/// </summary>
|
||||
MUInt16,
|
||||
|
||||
/// <summary>
|
||||
/// Int32 array.
|
||||
/// </summary>
|
||||
MInt32,
|
||||
|
||||
/// <summary>
|
||||
/// UInt32 array.
|
||||
/// </summary>
|
||||
MUInt32,
|
||||
|
||||
/// <summary>
|
||||
/// Int64 array.
|
||||
/// </summary>
|
||||
MInt64,
|
||||
|
||||
/// <summary>
|
||||
/// UInt64 array.
|
||||
/// </summary>
|
||||
MUInt64,
|
||||
|
||||
/// <summary>
|
||||
/// Single-precision floating point array.
|
||||
/// </summary>
|
||||
MSingle,
|
||||
|
||||
/// <summary>
|
||||
/// Double-precision floating point array.
|
||||
/// </summary>
|
||||
MDouble,
|
||||
|
||||
/// <summary>
|
||||
/// Cell array.
|
||||
/// </summary>
|
||||
MCell,
|
||||
|
||||
/// <summary>
|
||||
/// Logical array.
|
||||
/// </summary>
|
||||
MLogical,
|
||||
}
|
||||
}
|
@ -1,15 +1,27 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper around IntPtr to array in unmanaged memory.
|
||||
/// </summary>
|
||||
internal sealed class MemoryHandle : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MemoryHandle"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sizeInBytes">Size of the memory to be allocated.</param>
|
||||
internal MemoryHandle(int sizeInBytes)
|
||||
{
|
||||
Handle = Marshal.AllocHGlobal(sizeInBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets wrapped IntPtr.
|
||||
/// </summary>
|
||||
internal IntPtr Handle { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Array of HDF references stored in an HDF dataset.
|
||||
/// </summary>
|
||||
internal struct ReferenceArray : IDisposable, IEnumerable<Dataset>
|
||||
{
|
||||
public Dataset Dataset { get; }
|
||||
|
||||
public int Size { get; }
|
||||
|
||||
public MemoryHandle Buf { get; }
|
||||
|
||||
public Dataset[] References { get; }
|
||||
private readonly Dataset[] references;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReferenceArray"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="dataset">Containing dataset.</param>
|
||||
/// <param name="size">Array size.</param>
|
||||
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,23 +38,45 @@ namespace MatFileHandler.Hdf
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets containing dataset.
|
||||
/// </summary>
|
||||
public Dataset Dataset { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets references.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Dataset> References => references;
|
||||
|
||||
/// <summary>
|
||||
/// Gets array size.
|
||||
/// </summary>
|
||||
public int Size { get; }
|
||||
|
||||
private MemoryHandle Buf { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<Dataset> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<Dataset>)References).GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return References.GetEnumerator();
|
||||
|
@ -1,22 +1,42 @@
|
||||
using System.Linq;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System.Linq;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// HDF space.
|
||||
/// </summary>
|
||||
internal struct Space
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Space"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="id">Space id.</param>
|
||||
public Space(long id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets space id.
|
||||
/// </summary>
|
||||
public long Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get space rank.
|
||||
/// </summary>
|
||||
/// <returns>Space rank.</returns>
|
||||
public int GetRank()
|
||||
{
|
||||
return H5S.get_simple_extent_ndims(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get dimensions of the space.
|
||||
/// </summary>
|
||||
/// <returns>Space dimensions.</returns>
|
||||
public int[] GetDimensions()
|
||||
{
|
||||
var dims = new ulong[GetRank()];
|
||||
|
@ -1,70 +1,147 @@
|
||||
using System;
|
||||
// Copyright 2017-2018 Alexander Luzgarev
|
||||
|
||||
using System;
|
||||
using HDF.PInvoke;
|
||||
|
||||
namespace MatFileHandler.Hdf
|
||||
{
|
||||
/// <summary>
|
||||
/// HDF type.
|
||||
/// </summary>
|
||||
internal struct Type
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Type"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="id">Type id.</param>
|
||||
public Type(long id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF string type.
|
||||
/// </summary>
|
||||
public static Type CS1 => new Type(H5T.C_S1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF double type.
|
||||
/// </summary>
|
||||
public static Type NativeDouble => new Type(H5T.NATIVE_DOUBLE);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF float (single) type.
|
||||
/// </summary>
|
||||
public static Type NativeFloat => new Type(H5T.NATIVE_FLOAT);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF int type.
|
||||
/// </summary>
|
||||
public static Type NativeInt => new Type(H5T.NATIVE_INT);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF int16 type.
|
||||
/// </summary>
|
||||
public static Type NativeInt16 => new Type(H5T.NATIVE_INT16);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF int32 type.
|
||||
/// </summary>
|
||||
public static Type NativeInt32 => new Type(H5T.NATIVE_INT32);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF int64 type.
|
||||
/// </summary>
|
||||
public static Type NativeInt64 => new Type(H5T.NATIVE_INT64);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF int8 type.
|
||||
/// </summary>
|
||||
public static Type NativeInt8 => new Type(H5T.NATIVE_INT8);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF uint type.
|
||||
/// </summary>
|
||||
public static Type NativeUInt => new Type(H5T.NATIVE_UINT);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF uint16 type
|
||||
/// </summary>
|
||||
public static Type NativeUInt16 => new Type(H5T.NATIVE_UINT16);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF uint32 type.
|
||||
/// </summary>
|
||||
public static Type NativeUInt32 => new Type(H5T.NATIVE_UINT32);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF uint64 type.
|
||||
/// </summary>
|
||||
public static Type NativeUInt64 => new Type(H5T.NATIVE_UINT64);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF uint8 type.
|
||||
/// </summary>
|
||||
public static Type NativeUInt8 => new Type(H5T.NATIVE_UINT8);
|
||||
|
||||
/// <summary>
|
||||
/// Gets HDF reference type.
|
||||
/// </summary>
|
||||
public static Type Reference => new Type(H5T.STD_REF_OBJ);
|
||||
|
||||
/// <summary>
|
||||
/// Gets type id.
|
||||
/// </summary>
|
||||
public long Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create compound type of given size.
|
||||
/// </summary>
|
||||
/// <param name="size">Size of the type.</param>
|
||||
/// <returns>The created type.</returns>
|
||||
public static Type CreateCompound(int size)
|
||||
{
|
||||
return new Type(H5T.create(H5T.class_t.COMPOUND, (IntPtr)size));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get class of the type.
|
||||
/// </summary>
|
||||
/// <returns>Class of the type.</returns>
|
||||
public Class GetClass()
|
||||
{
|
||||
return new Class(H5T.get_class(Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get size of the type.
|
||||
/// </summary>
|
||||
/// <returns>Size of the type.</returns>
|
||||
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);
|
||||
/// <summary>
|
||||
/// Insert a field into the type.
|
||||
/// </summary>
|
||||
/// <param name="name">Field name.</param>
|
||||
/// <param name="fieldType">Field type.</param>
|
||||
public void InsertField(string name, Type fieldType)
|
||||
{
|
||||
H5T.insert(Id, name, IntPtr.Zero, fieldType.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create type copy with same class and given size.
|
||||
/// </summary>
|
||||
/// <param name="size">New size.</param>
|
||||
/// <returns>New type.</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader of HDF files containing MATLAB data.
|
||||
/// </summary>
|
||||
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<IVariable> variables;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HdfFileReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="fileId">File id to read data from.</param>
|
||||
internal HdfFileReader(long fileId)
|
||||
{
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read MATLAB data from the HDF file.
|
||||
/// </summary>
|
||||
/// <returns>MATLAB data file contents.</returns>
|
||||
internal IMatFile Read()
|
||||
{
|
||||
variables = new List<IVariable>();
|
||||
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<T>(data, arrayType);
|
||||
return new MatNumericalArrayOf<T>(dims, convertedData);
|
||||
@ -418,7 +434,7 @@ namespace MatFileHandler
|
||||
private static IArray ReadSparseArray<T>(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(
|
||||
@ -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<T>(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();
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ namespace MatFileHandler
|
||||
Version = version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets raw byte contents of the header.
|
||||
/// </summary>
|
||||
public byte[] RawBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader for MATLAB HDF (-v7.3) files.
|
||||
/// </summary>
|
||||
internal static class MatFileHdfReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Continue reading MATLAB HDF file after reading the MATLAB header.
|
||||
/// </summary>
|
||||
/// <param name="header">MATLAB header that was read.</param>
|
||||
/// <param name="stream">Stream to read the rest of the file from.</param>
|
||||
/// <returns>MATLAB data file contents.</returns>
|
||||
internal static IMatFile ContinueReadingHdfFile(Header header, Stream stream)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Continue reading old-style (Level 5) MATLAB file.
|
||||
/// </summary>
|
||||
/// <param name="header">Header that was already read.</param>
|
||||
/// <param name="reader">Reader for reading the rest of the file.</param>
|
||||
/// <returns>MATLAB data file contents.</returns>
|
||||
internal static IMatFile ContinueReadingLevel5File(Header header, BinaryReader reader)
|
||||
{
|
||||
var rawVariables = ReadRawVariables(reader, header.SubsystemDataOffset);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of the variable in the source file.</param>
|
||||
/// <param name="dataElement">Data element parsed from the file.</param>
|
||||
/// <param name="flags">Array flags.</param>
|
||||
/// <param name="name">Variable name.</param>
|
||||
internal RawVariable(long offset, DataElement dataElement, ArrayFlags flags, string name)
|
||||
{
|
||||
Offset = offset;
|
||||
@ -30,8 +32,14 @@ namespace MatFileHandler
|
||||
/// </summary>
|
||||
public DataElement DataElement { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets array flags.
|
||||
/// </summary>
|
||||
public ArrayFlags Flags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets variable name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
|
Loading…
x
Reference in New Issue
Block a user