Пример #1
0
        private Span <byte> GetBuffer <T>(out T[] result) where T : struct
        {
            // first, get byte size
            var byteSize = H5Utils.CalculateSize(this.Dataspace.DimensionSizes, this.Dataspace.Type) * this.Datatype.Size;

            // second, convert file type (e.g. 2 bytes) to T (e.g. 4 bytes)
            var arraySize = byteSize / (ulong)Unsafe.SizeOf <T>();

            // finally, create buffer
            result = new T[arraySize];
            var buffer = MemoryMarshal.AsBytes(result.AsSpan());

            return(buffer);
        }
        public AttributeMessage(H5BinaryReader reader, Superblock superblock) : base(reader)
        {
            //var a = reader.ReadBytes(200);
            // version
            this.Version = reader.ReadByte();

            if (this.Version == 1)
            {
                reader.ReadByte();
            }
            else
            {
                this.Flags = (AttributeMessageFlags)reader.ReadByte();
            }

            // name size
            var nameSize = reader.ReadUInt16();

            // datatype size
            var datatypeSize = reader.ReadUInt16();

            // dataspace size
            var dataspaceSize = reader.ReadUInt16();

            // name character set encoding
            if (this.Version == 3)
            {
                _nameEncoding = (CharacterSetEncoding)reader.ReadByte();
            }

            // name
            if (this.Version == 1)
            {
                this.Name = H5Utils.ReadNullTerminatedString(reader, pad: true, encoding: _nameEncoding);
            }
            else
            {
                this.Name = H5Utils.ReadNullTerminatedString(reader, pad: false, encoding: _nameEncoding);
            }

            // datatype
            this.Datatype = new DatatypeMessage(reader);

            if (this.Version == 1)
            {
                var paddedSize    = (int)(Math.Ceiling(datatypeSize / 8.0) * 8);
                var remainingSize = paddedSize - datatypeSize;
                reader.ReadBytes(remainingSize);
            }

            // dataspace
            this.Dataspace = new DataspaceMessage(reader, superblock);

            if (this.Version == 1)
            {
                var paddedSize    = (int)(Math.Ceiling(dataspaceSize / 8.0) * 8);
                var remainingSize = paddedSize - dataspaceSize;
                this.Reader.Seek(remainingSize, SeekOrigin.Current);
            }

            // data
            var byteSize = H5Utils.CalculateSize(this.Dataspace.DimensionSizes, this.Dataspace.Type) * this.Datatype.Size;

            this.Data = reader.ReadBytes((int)byteSize);
        }
Пример #3
0
        public static unsafe T[] ReadCompound <T>(
            DatatypeMessage datatype,
            DataspaceMessage dataspace,
            Superblock superblock,
            Span <byte> data,
            Func <FieldInfo, string> getName) where T : struct
        {
            if (datatype.Class != DatatypeMessageClass.Compound)
            {
                throw new Exception($"This method can only be used for data type class '{DatatypeMessageClass.Compound}'.");
            }

            var type         = typeof(T);
            var fieldInfoMap = new Dictionary <string, FieldProperties>();

            foreach (var fieldInfo in type.GetFields())
            {
                var name = getName(fieldInfo);

                var isNotSupported = H5Utils.IsReferenceOrContainsReferences(fieldInfo.FieldType) &&
                                     fieldInfo.FieldType != typeof(string);

                if (isNotSupported)
                {
                    throw new Exception("Nested nullable fields are not supported.");
                }

                fieldInfoMap[name] = new FieldProperties()
                {
                    FieldInfo = fieldInfo,
                    Offset    = Marshal.OffsetOf(type, fieldInfo.Name)
                };
            }

            var properties = datatype.Properties
                             .Cast <CompoundPropertyDescription>()
                             .ToList();

            var sourceOffset      = 0UL;
            var sourceRawBytes    = data;
            var sourceElementSize = datatype.Size;

            var targetArraySize   = H5Utils.CalculateSize(dataspace.DimensionSizes, dataspace.Type);
            var targetArray       = new T[targetArraySize];
            var targetElementSize = Marshal.SizeOf <T>();

            for (int i = 0; i < targetArray.Length; i++)
            {
                var targetRawBytes = new byte[targetElementSize];
                var stringMap      = new Dictionary <FieldProperties, string>();

                foreach (var property in properties)
                {
                    if (!fieldInfoMap.TryGetValue(property.Name, out var fieldInfo))
                    {
                        throw new Exception($"The property named '{property.Name}' in the HDF5 data type does not exist in the provided structure of type '{typeof(T)}'.");
                    }

                    var fieldSize = (int)property.MemberTypeMessage.Size;

                    // strings
                    if (fieldInfo.FieldInfo.FieldType == typeof(string))
                    {
                        var sourceIndex    = (int)(sourceOffset + property.MemberByteOffset);
                        var sourceIndexEnd = sourceIndex + fieldSize;
                        var targetIndex    = fieldInfo.Offset.ToInt64();
                        var value          = H5Utils.ReadString(property.MemberTypeMessage, sourceRawBytes[sourceIndex..sourceIndexEnd], superblock);
Пример #4
0
        private T[] ReadChunked <T>() where T : struct
        {
            var buffer = this.GetBuffer <T>(out var result);

            if (this.DataLayout is DataLayoutMessage12 layout12)
            {
                if (this.Context.Superblock.IsUndefinedAddress(layout12.DataAddress))
                {
                    if (this.FillValue.IsDefined)
                    {
                        buffer.Fill(this.FillValue.Value);
                    }
                }
                else
                {
                    var chunkSize = H5Utils.CalculateSize(layout12.DimensionSizes);
                    this.Context.Reader.Seek((int)layout12.DataAddress, SeekOrigin.Begin);
                    this.ReadChunkedBTree1(buffer, layout12.Rank, chunkSize);
                }
            }
            else if (this.DataLayout is DataLayoutMessage4 layout4)
            {
                var chunked4  = (ChunkedStoragePropertyDescription4)layout4.Properties;
                var chunkSize = H5Utils.CalculateSize(chunked4.DimensionSizes);

                if (this.Context.Superblock.IsUndefinedAddress(chunked4.Address))
                {
                    if (this.FillValue.IsDefined)
                    {
                        buffer.Fill(this.FillValue.Value);
                    }
                }
                else
                {
                    this.Context.Reader.Seek((int)chunked4.Address, SeekOrigin.Begin);

                    switch (chunked4.ChunkIndexingType)
                    {
                    // the current, maximum, and chunk dimension sizes are all the same
                    case ChunkIndexingType.SingleChunk:
                        var singleChunkInfo = (SingleChunkIndexingInformation)chunked4.IndexingTypeInformation;
                        this.ReadChunk(buffer, chunkSize);
                        break;

                    // fixed maximum dimension sizes
                    // no filter applied to the dataset
                    // the timing for the space allocation of the dataset chunks is H5P_ALLOC_TIME_EARLY
                    case ChunkIndexingType.Implicit:
                        var @implicitInfo = (ImplicitIndexingInformation)chunked4.IndexingTypeInformation;
                        this.Context.Reader.Read(buffer);
                        break;

                    // fixed maximum dimension sizes
                    case ChunkIndexingType.FixedArray:
                        var fixedArrayInfo = (FixedArrayIndexingInformation)chunked4.IndexingTypeInformation;
                        this.ReadFixedArray(buffer, chunkSize);
                        break;

                    // only one dimension of unlimited extent
                    case ChunkIndexingType.ExtensibleArray:
                        var extensibleArrayInfo = (ExtensibleArrayIndexingInformation)chunked4.IndexingTypeInformation;
                        this.ReadExtensibleArray(buffer, chunkSize);
                        break;

                    // more than one dimension of unlimited extent
                    case ChunkIndexingType.BTree2:
                        var btree2Info = (BTree2IndexingInformation)chunked4.IndexingTypeInformation;
                        this.ReadChunkedBTree2(buffer, (byte)(chunked4.Rank - 1), chunkSize);
                        break;

                    default:
                        break;
                    }
                }
            }
            else if (this.DataLayout is DataLayoutMessage3 layout3)
            {
                var chunked3 = (ChunkedStoragePropertyDescription3)layout3.Properties;

                if (this.Context.Superblock.IsUndefinedAddress(chunked3.Address))
                {
                    if (this.FillValue.IsDefined)
                    {
                        buffer.Fill(this.FillValue.Value);
                    }
                }
                else
                {
                    var chunkSize = H5Utils.CalculateSize(chunked3.DimensionSizes);
                    this.Context.Reader.Seek((int)chunked3.Address, SeekOrigin.Begin);
                    this.ReadChunkedBTree1(buffer, (byte)(chunked3.Rank - 1), chunkSize);
                }
            }
            else
            {
                throw new Exception($"Data layout message type '{this.DataLayout.GetType().Name}' is not supported.");
            }

            this.EnsureEndianness(buffer);
            return(result);
        }
Пример #5
0
        public AttributeMessage(H5Context context, ObjectHeader objectHeader) : base(context.Reader)
        {
            _context = context;

            // version
            this.Version = context.Reader.ReadByte();

            if (this.Version == 1)
            {
                context.Reader.ReadByte();
            }
            else
            {
                this.Flags = (AttributeMessageFlags)context.Reader.ReadByte();
            }

            // name size
            var nameSize = context.Reader.ReadUInt16();

            // datatype size
            var datatypeSize = context.Reader.ReadUInt16();

            // dataspace size
            var dataspaceSize = context.Reader.ReadUInt16();

            // name character set encoding
            if (this.Version == 3)
            {
                _nameEncoding = (CharacterSetEncoding)context.Reader.ReadByte();
            }

            // name
            if (this.Version == 1)
            {
                this.Name = H5Utils.ReadNullTerminatedString(context.Reader, pad: true, encoding: _nameEncoding);
            }
            else
            {
                this.Name = H5Utils.ReadNullTerminatedString(context.Reader, pad: false, encoding: _nameEncoding);
            }

            // datatype
            var flags1 = this.Flags.HasFlag(AttributeMessageFlags.SharedDatatype)
                ? MessageFlags.Shared
                : MessageFlags.NoFlags;

            this.Datatype = objectHeader.DecodeMessage(flags1,
                                                       () => new DatatypeMessage(context.Reader));

            if (this.Version == 1)
            {
                var paddedSize    = (int)(Math.Ceiling(datatypeSize / 8.0) * 8);
                var remainingSize = paddedSize - datatypeSize;
                context.Reader.ReadBytes(remainingSize);
            }

            // dataspace
            var flags2 = this.Flags.HasFlag(AttributeMessageFlags.SharedDataspace)
                ? MessageFlags.Shared
                : MessageFlags.NoFlags;

            this.Dataspace = objectHeader.DecodeMessage(flags2,
                                                        () => new DataspaceMessage(context.Reader, context.Superblock));

            if (this.Version == 1)
            {
                var paddedSize    = (int)(Math.Ceiling(dataspaceSize / 8.0) * 8);
                var remainingSize = paddedSize - dataspaceSize;
                this.Reader.Seek(remainingSize, SeekOrigin.Current);
            }

            // data
            var byteSize = H5Utils.CalculateSize(this.Dataspace.DimensionSizes, this.Dataspace.Type) * this.Datatype.Size;

            this.Data = context.Reader.ReadBytes((int)byteSize);
        }