public static long GetHdfTypeIdFromType(Type type) { return(TypeConversionHelper.GetHdfTypeIdFromType(-1, type)); }
public static long GetHdfTypeIdFromType(long fileId, Type type) { Type elementType; elementType = type.IsArray ? type.GetElementType() : type; if (elementType == typeof(bool)) { return(H5T.NATIVE_UINT8); } else if (elementType == typeof(Byte)) { return(H5T.NATIVE_UINT8); } else if (elementType == typeof(SByte)) { return(H5T.NATIVE_INT8); } else if (elementType == typeof(UInt16)) { return(H5T.NATIVE_UINT16); } else if (elementType == typeof(Int16)) { return(H5T.NATIVE_INT16); } else if (elementType == typeof(UInt32)) { return(H5T.NATIVE_UINT32); } else if (elementType == typeof(Int32)) { return(H5T.NATIVE_INT32); } else if (elementType == typeof(UInt64)) { return(H5T.NATIVE_UINT64); } else if (elementType == typeof(Int64)) { return(H5T.NATIVE_INT64); } else if (elementType == typeof(Single)) { return(H5T.NATIVE_FLOAT); } else if (elementType == typeof(Double)) { return(H5T.NATIVE_DOUBLE); } else if (elementType == typeof(string) || elementType == typeof(IntPtr)) { long typeId = 0; if (H5I.is_valid(fileId) > 0 && H5L.exists(fileId, "string_t") > 0) { typeId = H5T.open(fileId, "string_t"); } else { typeId = H5T.copy(H5T.C_S1); H5T.set_size(typeId, H5T.VARIABLE); H5T.set_cset(typeId, H5T.cset_t.UTF8); if (fileId > -1 && H5T.commit(fileId, "string_t", typeId) < 0) { throw new Exception(ErrorMessage.TypeConversionHelper_CouldNotCommitDataType); } } return(typeId); } else if (elementType.IsValueType && !elementType.IsPrimitive && !elementType.IsEnum) { long typeId = 0; if (H5I.is_valid(fileId) > 0 && H5L.exists(fileId, elementType.Name) > 0) { typeId = H5T.open(fileId, elementType.Name); } else { typeId = H5T.create(H5T.class_t.COMPOUND, new IntPtr(Marshal.SizeOf(elementType))); foreach (FieldInfo fieldInfo in elementType.GetFields()) { long fieldType = -1; fieldType = TypeConversionHelper.GetHdfTypeIdFromType(fileId, fieldInfo.FieldType); H5T.insert(typeId, fieldInfo.Name, Marshal.OffsetOf(elementType, fieldInfo.Name), fieldType); if (H5I.is_valid(fieldType) > 0) { H5T.close(fieldType); } } if (fileId > -1 && H5T.commit(fileId, elementType.Name, typeId) < 0) { throw new Exception(ErrorMessage.TypeConversionHelper_CouldNotCommitDataType); } } return(typeId); } else { throw new NotSupportedException(); } }
public static void PrepareAttribute <T>(long locationId, string name, T[] valueSet, ulong[] dimensionLimitSet, bool initializeAttribute, [CallerMemberName()] string callerMemberName = "") { Contract.Requires(valueSet != null, nameof(valueSet)); long fileId = -1; long typeId = -1; long attributeId = -1; ulong[] dimensionSet; bool isNew; Type elementType; dimensionSet = new ulong[] { 0 }; elementType = typeof(T); try { fileId = H5I.get_file_id(locationId); // create attribute typeId = TypeConversionHelper.GetHdfTypeIdFromType(fileId, elementType); (attributeId, isNew) = IOHelper.OpenOrCreateAttribute(locationId, name, typeId, (ulong)valueSet.LongLength, dimensionLimitSet); // write attribute data (regenerate attribute if necessary) if (initializeAttribute) { ulong[] oldValueSetCount; if (!isNew && callerMemberName != nameof(IOHelper.PrepareAttribute)) { oldValueSetCount = IOHelper.PrepareAttributeValueSet(attributeId, ref valueSet, false); } else { oldValueSetCount = new ulong[1] { (ulong)valueSet.Count() } }; if (valueSet.Count() == (int)oldValueSetCount[0]) { IOHelper.Write(attributeId, valueSet, DataContainerType.Attribute); } else { H5A.close(attributeId); H5A.delete(locationId, name); IOHelper.PrepareAttribute(locationId, name, valueSet, dimensionLimitSet, true); } } } finally { if (H5I.is_valid(attributeId) > 0) { H5A.close(attributeId); } if (H5I.is_valid(typeId) > 0) { H5T.close(typeId); } if (H5I.is_valid(fileId) > 0) { H5F.close(fileId); } } }
public static unsafe void Write <T>(long dataTargetId, T[] valueSet, DataContainerType dataContainerType) { Contract.Requires(valueSet != null, nameof(valueSet)); long typeId = -1; int elementTypeSize; int byteLength; IntPtr valueSetPointer; GCHandle gcHandle; Type elementType; elementTypeSize = 0; byteLength = 0; valueSetPointer = default; gcHandle = default; elementType = typeof(T); try { typeId = TypeConversionHelper.GetHdfTypeIdFromType(elementType); if (elementType == typeof(string)) { elementTypeSize = Marshal.SizeOf <IntPtr>(); } else if (elementType == typeof(bool)) { elementTypeSize = Marshal.SizeOf <byte>(); } else { elementTypeSize = Marshal.SizeOf(elementType); } byteLength = elementTypeSize * valueSet.Count(); if (elementType.IsPrimitive) { gcHandle = GCHandle.Alloc(valueSet, GCHandleType.Pinned); valueSetPointer = gcHandle.AddrOfPinnedObject(); } else if (elementType == typeof(string)) { IntPtr[] intPtrSet = valueSet.Cast <string>().Select(x => Marshal.StringToHGlobalAnsi(x)).ToArray(); // utf8 ? valueSetPointer = Marshal.AllocHGlobal(byteLength); Marshal.Copy(intPtrSet, 0, valueSetPointer, intPtrSet.Count()); } else if (elementType.IsValueType && !elementType.IsPrimitive && !elementType.IsEnum) { IntPtr sourcePtr; int counter; counter = 0; valueSetPointer = Marshal.AllocHGlobal(byteLength); valueSet.Cast <ValueType>().ToList().ForEach(x => { Span <byte> source; Span <byte> target; sourcePtr = Marshal.AllocHGlobal(elementTypeSize); Marshal.StructureToPtr(x, sourcePtr, false); source = new Span <byte>(sourcePtr.ToPointer(), Marshal.SizeOf <T>()); target = new Span <byte>(IntPtr.Add(valueSetPointer, elementTypeSize * counter).ToPointer(), Marshal.SizeOf <T>()); source.CopyTo(target); counter += 1; Marshal.FreeHGlobal(sourcePtr); }); } else { throw new NotSupportedException(); } switch (dataContainerType) { case DataContainerType.Attribute: if (H5A.write(dataTargetId, typeId, valueSetPointer) < 0) { throw new Exception(ErrorMessage.IOHelper_CouldNotWriteAttribute); } break; case DataContainerType.Dataset: if (H5D.write(dataTargetId, typeId, H5S.ALL, H5S.ALL, H5P.DEFAULT, valueSetPointer) < 0) { throw new Exception(ErrorMessage.IOHelper_CouldNotWriteDataset); } break; default: throw new NotSupportedException(); } } finally { if (gcHandle.IsAllocated) { gcHandle.Free(); } else { Marshal.FreeHGlobal(valueSetPointer); } if (H5I.is_valid(typeId) > 0) { H5T.close(typeId); } } }
public static unsafe T[] Read <T>(long dataPortId, DataContainerType dataContainerType, long dataspaceId = -1) { long dataspaceId_file = -1; long dataspaceId_buffer = -1; long typeId = -1; long elementCount; int elementTypeSize; int byteLength; IntPtr bufferPtr; Type elementType; T[] returnValue; elementTypeSize = 0; byteLength = 0; bufferPtr = IntPtr.Zero; elementType = typeof(T); returnValue = null; try { if (dataspaceId > -1) { dataspaceId = H5S.copy(dataspaceId); } switch (dataContainerType) { case DataContainerType.Attribute: if (dataspaceId == -1) { dataspaceId = H5A.get_space(dataPortId); } break; case DataContainerType.Dataset: if (dataspaceId == -1) { dataspaceId = H5D.get_space(dataPortId); } dataspaceId_file = dataspaceId; break; default: throw new NotSupportedException(); } if (elementType == typeof(string)) { elementTypeSize = Marshal.SizeOf <IntPtr>(); } else if (elementType == typeof(bool)) { elementTypeSize = Marshal.SizeOf <byte>(); } else { elementTypeSize = Marshal.SizeOf(elementType); } elementCount = H5S.get_select_npoints(dataspaceId); byteLength = (int)elementCount * elementTypeSize; bufferPtr = Marshal.AllocHGlobal(byteLength); typeId = TypeConversionHelper.GetHdfTypeIdFromType(elementType); switch (dataContainerType) { case DataContainerType.Attribute: if (H5A.read(dataPortId, typeId, bufferPtr) < 0) { throw new Exception(ErrorMessage.IOHelper_CouldNotReadAttribute); } break; case DataContainerType.Dataset: dataspaceId_buffer = H5S.create_simple(1, new ulong[] { (ulong)elementCount }, new ulong[] { (ulong)elementCount }); if (H5D.read(dataPortId, typeId, dataspaceId_buffer, dataspaceId_file, H5P.DEFAULT, bufferPtr) < 0) { throw new Exception(ErrorMessage.IOHelper_CouldNotReadDataset); } break; default: throw new NotSupportedException(); } if (elementType.IsPrimitive) { T[] genericSet; GCHandle gcHandle; byte[] byteSet; genericSet = new T[(int)elementCount]; gcHandle = GCHandle.Alloc(genericSet, GCHandleType.Pinned); byteSet = new byte[byteLength]; Marshal.Copy(bufferPtr, byteSet, 0, byteLength); Marshal.Copy(byteSet, 0, gcHandle.AddrOfPinnedObject(), byteLength); returnValue = genericSet; gcHandle.Free(); } else if (elementType == typeof(string)) { IntPtr[] intPtrSet; intPtrSet = new IntPtr[(int)elementCount]; Marshal.Copy(bufferPtr, intPtrSet, 0, (int)elementCount); returnValue = intPtrSet.Select(x => { // keep this, otherwise °C gets read-in wrongly on Linux // (https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.ptrtostringansi?view=net-5.0) string result = IOHelper.PtrToStringAnsiWithEncoding(x, Encoding.GetEncoding(1252)); H5.free_memory(x); return(result); }).Cast <T>().ToArray(); } else if (elementType.IsValueType && !elementType.IsPrimitive && !elementType.IsEnum) { T[] structSet; int offset; structSet = new T[(int)elementCount]; offset = 0; Enumerable.Range(0, (int)elementCount).ToList().ForEach(x => { structSet[x] = Marshal.PtrToStructure <T>(IntPtr.Add(bufferPtr, offset)); offset += elementTypeSize; }); returnValue = structSet; } else { throw new NotSupportedException(); } } finally { Marshal.FreeHGlobal(bufferPtr); if (H5I.is_valid(typeId) > 0) { H5T.close(typeId); } if (H5I.is_valid(dataspaceId_buffer) > 0) { H5S.close(dataspaceId_buffer); } if (H5I.is_valid(dataspaceId) > 0) { H5S.close(dataspaceId); } } return(returnValue); }