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();
            }
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
        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);
                }
            }
        }
Example #5
0
        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);
        }