Careful disposal
This commit is contained in:
parent
99558d96c4
commit
82f43a7e5d
@ -9,6 +9,83 @@ using HDF.PInvoke;
|
|||||||
|
|
||||||
namespace MatFileHandler
|
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; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Handle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(Handle);
|
||||||
|
Handle = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal enum HdfMatlabClass
|
internal enum HdfMatlabClass
|
||||||
{
|
{
|
||||||
MEmpty,
|
MEmpty,
|
||||||
@ -385,18 +462,22 @@ namespace MatFileHandler
|
|||||||
switch (object_info.type)
|
switch (object_info.type)
|
||||||
{
|
{
|
||||||
case H5O.type_t.DATASET:
|
case H5O.type_t.DATASET:
|
||||||
var datasetId = H5D.open(group, variableName);
|
using (var dataset = new Dataset(group, variableName))
|
||||||
var value = ReadDataset(datasetId);
|
{
|
||||||
variables.Add(new MatVariable(value, variableName, false));
|
var value = ReadDataset(dataset.Id);
|
||||||
|
variables.Add(new MatVariable(value, variableName, false));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case H5O.type_t.GROUP:
|
case H5O.type_t.GROUP:
|
||||||
if (variableName == "#refs#")
|
if (variableName == "#refs#")
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var groupId = H5G.open(group, variableName);
|
using (var subGroup = new Group(group, variableName))
|
||||||
var groupValue = ReadGroup(groupId);
|
{
|
||||||
variables.Add(new MatVariable(groupValue, variableName, false));
|
var groupValue = ReadGroup(subGroup.Id);
|
||||||
|
variables.Add(new MatVariable(groupValue, variableName, false));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
@ -406,23 +487,26 @@ namespace MatFileHandler
|
|||||||
|
|
||||||
private static string GetMatlabClassOfDataset(long datasetId)
|
private static string GetMatlabClassOfDataset(long datasetId)
|
||||||
{
|
{
|
||||||
var attributeId = H5A.open_by_name(datasetId, ".", "MATLAB_class");
|
using (var attribute = new Attribute(datasetId, "MATLAB_class"))
|
||||||
|
|
||||||
var typeId = H5A.get_type(attributeId);
|
|
||||||
var cl = H5T.get_class(typeId);
|
|
||||||
if (cl != H5T.class_t.STRING)
|
|
||||||
{
|
{
|
||||||
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)
|
private static int[] GetDimensionsOfDataset(long datasetId)
|
||||||
@ -492,36 +576,39 @@ namespace MatFileHandler
|
|||||||
private static string[] ReadFieldNames(long groupId)
|
private static string[] ReadFieldNames(long groupId)
|
||||||
{
|
{
|
||||||
// Try to read fields from MATLAB_fields.
|
// Try to read fields from MATLAB_fields.
|
||||||
var attrId = H5A.open_by_name(groupId, ".", "MATLAB_fields");
|
using (var attr = new Attribute(groupId, "MATLAB_fields"))
|
||||||
if (attrId == 0)
|
|
||||||
{
|
{
|
||||||
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)
|
private static H5O.type_t GetObjectType(long groupId, string fieldName)
|
||||||
@ -537,51 +624,57 @@ namespace MatFileHandler
|
|||||||
var firstObjectType = GetObjectType(groupId, fieldNames[0]);
|
var firstObjectType = GetObjectType(groupId, fieldNames[0]);
|
||||||
if (firstObjectType == H5O.type_t.DATASET)
|
if (firstObjectType == H5O.type_t.DATASET)
|
||||||
{
|
{
|
||||||
var firstFieldId = H5D.open(groupId, fieldNames[0]);
|
using (var firstField = new Dataset(groupId, fieldNames[0]))
|
||||||
var firstFieldTypeId = H5D.get_type(firstFieldId);
|
|
||||||
if (H5T.get_class(firstFieldTypeId) == H5T.class_t.REFERENCE)
|
|
||||||
{
|
{
|
||||||
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<string, List<IArray>>();
|
||||||
|
foreach (var fieldName in fieldNames)
|
||||||
|
{
|
||||||
|
var fieldType = GetObjectType(groupId, fieldName);
|
||||||
|
dictionary[fieldName] = new List<IArray>();
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
var dimensions = GetDimensionsOfDataset(firstFieldId);
|
throw new NotImplementedException();
|
||||||
var numberOfElements = dimensions.NumberOfElements();
|
|
||||||
var dictionary = new Dictionary<string, List<IArray>>();
|
|
||||||
foreach (var fieldName in fieldNames)
|
|
||||||
{
|
|
||||||
var fieldType = GetObjectType(groupId, fieldName);
|
|
||||||
dictionary[fieldName] = new List<IArray>();
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -634,18 +727,21 @@ namespace MatFileHandler
|
|||||||
private static IArray ReadCellArray(long datasetId, int[] dims)
|
private static IArray ReadCellArray(long datasetId, int[] dims)
|
||||||
{
|
{
|
||||||
var numberOfElements = dims.NumberOfElements();
|
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];
|
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(
|
H5D.read(datasetId, H5T.STD_REF_OBJ, H5S.ALL, H5S.ALL, H5P.DEFAULT, buf.Handle);
|
||||||
datasetId,
|
for (var i = 0; i < numberOfElements; i++)
|
||||||
H5P.DEFAULT,
|
{
|
||||||
H5R.type_t.OBJECT,
|
var fieldDataSet =
|
||||||
buf + (i * Marshal.SizeOf(default(IntPtr))));
|
H5R.dereference(
|
||||||
var dataset = ReadDataset(fieldDataSet);
|
datasetId,
|
||||||
elements[i] = dataset;
|
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);
|
return new HdfCellArray(dims, elements);
|
||||||
}
|
}
|
||||||
@ -715,11 +811,12 @@ namespace MatFileHandler
|
|||||||
|
|
||||||
private static byte[] ReadDataset(long datasetId, long elementType, int dataSize)
|
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];
|
var data = new byte[dataSize];
|
||||||
Marshal.Copy(dataBuffer, data, 0, dataSize);
|
using (var dataBuffer = new MemoryHandle(dataSize))
|
||||||
Marshal.FreeHGlobal(dataBuffer);
|
{
|
||||||
|
H5D.read(datasetId, elementType, H5S.ALL, H5S.ALL, H5P.DEFAULT, dataBuffer.Handle);
|
||||||
|
Marshal.Copy(dataBuffer.Handle, data, 0, dataSize);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user