diff --git a/MatFileHandler/HdfFileReader.cs b/MatFileHandler/HdfFileReader.cs
index f5af339..9fbefa5 100644
--- a/MatFileHandler/HdfFileReader.cs
+++ b/MatFileHandler/HdfFileReader.cs
@@ -9,6 +9,83 @@ using HDF.PInvoke;
namespace MatFileHandler
{
+ public struct Dataset : IDisposable
+ {
+ public long Id { get; private set; }
+
+ public Dataset(long groupId, string name)
+ {
+ Id = H5D.open(groupId, name);
+ }
+
+ public void Dispose()
+ {
+ if (Id != -1)
+ {
+ H5D.close(Id);
+ Id = -1;
+ }
+ }
+ }
+
+ public struct Group : IDisposable
+ {
+ public long Id { get; private set; }
+
+ public Group(long groupId, string name)
+ {
+ Id = H5G.open(groupId, name);
+ }
+
+ public void Dispose()
+ {
+ if (Id != -1)
+ {
+ H5G.close(Id);
+ Id = -1;
+ }
+ }
+ }
+
+ public struct Attribute : IDisposable
+ {
+ public long Id { get; private set; }
+
+ public Attribute(long locationId, string name)
+ {
+ Id = H5A.open_by_name(locationId, ".", name);
+ }
+
+ public void Dispose()
+ {
+ if (Id != -1)
+ {
+ H5A.close(Id);
+ Id = -1;
+ }
+ }
+ }
+
+ sealed class MemoryHandle : IDisposable
+ {
+ internal MemoryHandle(int sizeInBytes)
+ {
+ Handle = Marshal.AllocHGlobal(sizeInBytes);
+ }
+
+ internal IntPtr Handle { get; private set; }
+
+ ///
+ public void Dispose()
+ {
+ if (Handle != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(Handle);
+ Handle = IntPtr.Zero;
+ }
+ }
+ }
+
internal enum HdfMatlabClass
{
MEmpty,
@@ -385,18 +462,22 @@ namespace MatFileHandler
switch (object_info.type)
{
case H5O.type_t.DATASET:
- var datasetId = H5D.open(group, variableName);
- var value = ReadDataset(datasetId);
- variables.Add(new MatVariable(value, variableName, false));
+ using (var dataset = new Dataset(group, variableName))
+ {
+ var value = ReadDataset(dataset.Id);
+ variables.Add(new MatVariable(value, variableName, false));
+ }
break;
case H5O.type_t.GROUP:
if (variableName == "#refs#")
{
return 0;
}
- var groupId = H5G.open(group, variableName);
- var groupValue = ReadGroup(groupId);
- variables.Add(new MatVariable(groupValue, variableName, false));
+ using (var subGroup = new Group(group, variableName))
+ {
+ var groupValue = ReadGroup(subGroup.Id);
+ variables.Add(new MatVariable(groupValue, variableName, false));
+ }
break;
default:
throw new NotImplementedException();
@@ -406,23 +487,26 @@ namespace MatFileHandler
private static string GetMatlabClassOfDataset(long datasetId)
{
- var attributeId = H5A.open_by_name(datasetId, ".", "MATLAB_class");
-
- var typeId = H5A.get_type(attributeId);
- var cl = H5T.get_class(typeId);
- if (cl != H5T.class_t.STRING)
+ using (var attribute = new Attribute(datasetId, "MATLAB_class"))
{
- throw new NotImplementedException();
+ var typeId = H5A.get_type(attribute.Id);
+ var cl = H5T.get_class(typeId);
+ if (cl != H5T.class_t.STRING)
+ {
+ throw new NotImplementedException();
+ }
+ var classId = H5T.copy(H5T.C_S1);
+ var typeIdSize = (int)H5T.get_size(typeId);
+ H5T.set_size(classId, (IntPtr)typeIdSize);
+ var matlabClassNameBytes = new byte[typeIdSize];
+ using (var buf = new MemoryHandle(typeIdSize))
+ {
+ H5A.read(attribute.Id, classId, buf.Handle);
+ Marshal.Copy(buf.Handle, matlabClassNameBytes, 0, typeIdSize);
+ }
+
+ return Encoding.ASCII.GetString(matlabClassNameBytes);
}
- var classId = H5T.copy(H5T.C_S1);
- var typeIdSize = H5T.get_size(typeId);
- H5T.set_size(classId, typeIdSize);
- var buf = Marshal.AllocHGlobal(typeIdSize);
- H5A.read(attributeId, classId, buf);
- var matlabClassNameBytes = new byte[(int)typeIdSize];
- Marshal.Copy(buf, matlabClassNameBytes, 0, (int)typeIdSize);
- Marshal.FreeHGlobal(buf);
- return Encoding.ASCII.GetString(matlabClassNameBytes);
}
private static int[] GetDimensionsOfDataset(long datasetId)
@@ -492,36 +576,39 @@ namespace MatFileHandler
private static string[] ReadFieldNames(long groupId)
{
// Try to read fields from MATLAB_fields.
- var attrId = H5A.open_by_name(groupId, ".", "MATLAB_fields");
- if (attrId == 0)
+ using (var attr = new Attribute(groupId, "MATLAB_fields"))
{
- throw new NotImplementedException();
+ if (attr.Id == 0)
+ {
+ throw new NotImplementedException();
+ }
+ var spaceId = H5A.get_space(attr.Id);
+ var rank = H5S.get_simple_extent_ndims(spaceId);
+ var dims = new ulong[rank];
+ H5S.get_simple_extent_dims(spaceId, dims, null);
+ Array.Reverse(dims);
+ var dimensions = dims.Select(x => (int)x).ToArray();
+ var numberOfFields = dimensions.NumberOfElements();
+
+ var field_id = H5A.get_type(attr.Id);
+
+ var fieldNamePointersSizeInBytes = numberOfFields * Marshal.SizeOf(default(H5T.hvl_t));
+ var fieldNamePointers = new IntPtr[numberOfFields * 2];
+ using (var fieldNamesBuf = new MemoryHandle(fieldNamePointersSizeInBytes))
+ {
+ H5A.read(attr.Id, field_id, fieldNamesBuf.Handle);
+ Marshal.Copy(fieldNamesBuf.Handle, fieldNamePointers, 0, numberOfFields * 2);
+ }
+
+ var fieldNames = new string[numberOfFields];
+ for (var i = 0; i < numberOfFields; i++)
+ {
+ var stringLength = fieldNamePointers[i * 2];
+ var stringPointer = fieldNamePointers[(i * 2) + 1];
+ fieldNames[i] = Marshal.PtrToStringAnsi(stringPointer, (int)stringLength);
+ }
+ return fieldNames;
}
- var spaceId = H5A.get_space(attrId);
- var rank = H5S.get_simple_extent_ndims(spaceId);
- var dims = new ulong[rank];
- H5S.get_simple_extent_dims(spaceId, dims, null);
- Array.Reverse(dims);
- var dimensions = dims.Select(x => (int)x).ToArray();
- var numberOfFields = dimensions.NumberOfElements();
-
- var field_id = H5A.get_type(attrId);
-
- var fieldNamePointersSizeInBytes = numberOfFields * Marshal.SizeOf(default(H5T.hvl_t));
- var fieldNamesBuf = Marshal.AllocHGlobal(fieldNamePointersSizeInBytes);
- H5A.read(attrId, field_id, fieldNamesBuf);
-
- var fieldNamePointers = new IntPtr[numberOfFields * 2];
- Marshal.Copy(fieldNamesBuf, fieldNamePointers, 0, numberOfFields * 2);
- Marshal.FreeHGlobal(fieldNamesBuf);
- var fieldNames = new string[numberOfFields];
- for (var i = 0; i < numberOfFields; i++)
- {
- var stringLength = fieldNamePointers[i * 2];
- var stringPointer = fieldNamePointers[i * 2 + 1];
- fieldNames[i] = Marshal.PtrToStringAnsi(stringPointer, (int)stringLength);
- }
- return fieldNames;
}
private static H5O.type_t GetObjectType(long groupId, string fieldName)
@@ -537,51 +624,57 @@ namespace MatFileHandler
var firstObjectType = GetObjectType(groupId, fieldNames[0]);
if (firstObjectType == H5O.type_t.DATASET)
{
- var firstFieldId = H5D.open(groupId, fieldNames[0]);
- var firstFieldTypeId = H5D.get_type(firstFieldId);
- if (H5T.get_class(firstFieldTypeId) == H5T.class_t.REFERENCE)
+ using (var firstField = new Dataset(groupId, fieldNames[0]))
{
- if (H5A.exists_by_name(firstFieldId, ".", "MATLAB_class") != 0)
+ var firstFieldTypeId = H5D.get_type(firstField.Id);
+ if (H5T.get_class(firstFieldTypeId) == H5T.class_t.REFERENCE)
{
- throw new NotImplementedException();
+ if (H5A.exists_by_name(firstField.Id, ".", "MATLAB_class") != 0)
+ {
+ throw new NotImplementedException();
+ }
+ else
+ {
+ var dimensions = GetDimensionsOfDataset(firstField.Id);
+ var numberOfElements = dimensions.NumberOfElements();
+ var dictionary = new Dictionary>();
+ foreach (var fieldName in fieldNames)
+ {
+ var fieldType = GetObjectType(groupId, fieldName);
+ dictionary[fieldName] = new List();
+ switch (fieldType)
+ {
+ case H5O.type_t.DATASET:
+ using (var field = new Dataset(groupId, fieldName))
+ {
+ using (var buf = new MemoryHandle(Marshal.SizeOf(default(IntPtr)) * numberOfElements))
+ {
+ H5D.read(field.Id, H5T.STD_REF_OBJ, H5S.ALL, H5S.ALL, H5P.DEFAULT, buf.Handle);
+ for (var i = 0; i < numberOfElements; i++)
+ {
+ var fieldDataSet = H5R.dereference(
+ field.Id,
+ H5P.DEFAULT,
+ H5R.type_t.OBJECT,
+ buf.Handle + (i * Marshal.SizeOf(default(IntPtr))));
+ var dataset = ReadDataset(fieldDataSet);
+ dictionary[fieldName].Add(dataset);
+ }
+ }
+ }
+ break;
+ default:
+ throw new NotImplementedException();
+ }
+ }
+ return new HdfStructureArray(dimensions, dictionary);
+ }
}
else
{
- var dimensions = GetDimensionsOfDataset(firstFieldId);
- var numberOfElements = dimensions.NumberOfElements();
- var dictionary = new Dictionary>();
- foreach (var fieldName in fieldNames)
- {
- var fieldType = GetObjectType(groupId, fieldName);
- dictionary[fieldName] = new List();
- switch (fieldType)
- {
- case H5O.type_t.DATASET:
- var fieldId = H5D.open(groupId, fieldName);
- var buf = Marshal.AllocHGlobal(Marshal.SizeOf(default(IntPtr)) * numberOfElements);
- H5D.read(fieldId, H5T.STD_REF_OBJ, H5S.ALL, H5S.ALL, H5P.DEFAULT, buf);
- for (var i = 0; i < numberOfElements; i++)
- {
- var fieldDataSet = H5R.dereference(
- fieldId,
- H5P.DEFAULT,
- H5R.type_t.OBJECT,
- buf + (i * Marshal.SizeOf(default(IntPtr))));
- var dataset = ReadDataset(fieldDataSet);
- dictionary[fieldName].Add(dataset);
- }
- break;
- default:
- throw new NotImplementedException();
- }
- }
- return new HdfStructureArray(dimensions, dictionary);
+ throw new NotImplementedException();
}
}
- else
- {
- throw new NotImplementedException();
- }
}
else
{
@@ -634,18 +727,21 @@ namespace MatFileHandler
private static IArray ReadCellArray(long datasetId, int[] dims)
{
var numberOfElements = dims.NumberOfElements();
- var buf = Marshal.AllocHGlobal(Marshal.SizeOf(default(IntPtr)) * numberOfElements);
- H5D.read(datasetId, H5T.STD_REF_OBJ, H5S.ALL, H5S.ALL, H5P.DEFAULT, buf);
var elements = new IArray[numberOfElements];
- for (var i = 0; i < numberOfElements; i++)
+ using (var buf = new MemoryHandle(Marshal.SizeOf(default(IntPtr)) * numberOfElements))
{
- var fieldDataSet = H5R.dereference(
- datasetId,
- H5P.DEFAULT,
- H5R.type_t.OBJECT,
- buf + (i * Marshal.SizeOf(default(IntPtr))));
- var dataset = ReadDataset(fieldDataSet);
- elements[i] = dataset;
+ H5D.read(datasetId, H5T.STD_REF_OBJ, H5S.ALL, H5S.ALL, H5P.DEFAULT, buf.Handle);
+ for (var i = 0; i < numberOfElements; i++)
+ {
+ var fieldDataSet =
+ H5R.dereference(
+ datasetId,
+ H5P.DEFAULT,
+ H5R.type_t.OBJECT,
+ buf.Handle + (i * Marshal.SizeOf(default(IntPtr))));
+ var dataset = ReadDataset(fieldDataSet);
+ elements[i] = dataset;
+ }
}
return new HdfCellArray(dims, elements);
}
@@ -715,11 +811,12 @@ namespace MatFileHandler
private static byte[] ReadDataset(long datasetId, long elementType, int dataSize)
{
- var dataBuffer = Marshal.AllocHGlobal(dataSize);
- H5D.read(datasetId, elementType, H5S.ALL, H5S.ALL, H5P.DEFAULT, dataBuffer);
var data = new byte[dataSize];
- Marshal.Copy(dataBuffer, data, 0, dataSize);
- Marshal.FreeHGlobal(dataBuffer);
+ using (var dataBuffer = new MemoryHandle(dataSize))
+ {
+ H5D.read(datasetId, elementType, H5S.ALL, H5S.ALL, H5P.DEFAULT, dataBuffer.Handle);
+ Marshal.Copy(dataBuffer.Handle, data, 0, dataSize);
+ }
return data;
}