diff --git a/jhdf/src/main/java/io/jhdf/object/datatype/DataType.java b/jhdf/src/main/java/io/jhdf/object/datatype/DataType.java index 115b0762..5bdef643 100644 --- a/jhdf/src/main/java/io/jhdf/object/datatype/DataType.java +++ b/jhdf/src/main/java/io/jhdf/object/datatype/DataType.java @@ -15,12 +15,15 @@ import io.jhdf.exceptions.UnsupportedHdfException; import io.jhdf.storage.HdfBackingStorage; import io.jhdf.storage.HdfFileChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.util.BitSet; public abstract class DataType { + private static final Logger logger = LoggerFactory.getLogger(DataType.class); private final int version; private final int dataClass; private final int size; // In bytes @@ -42,7 +45,9 @@ public static DataType readDataType(ByteBuffer bb) { int version = Utils.bitsToInt(classAndVersion, 4, 4); int dataClass = Utils.bitsToInt(classAndVersion, 0, 4); - if (version == 0 || version > 3) { + if (version == 0) { + logger.warn("Datatype version 0 detected this is out of spec, attempting to read anyway"); + } else if (version > 3) { throw new HdfException("Unrecognized datatype version '" + version + "' detected"); } @@ -55,8 +60,8 @@ public static DataType readDataType(ByteBuffer bb) { return new FixedPoint(bb); case FloatingPoint.CLASS_ID: // Floating point return new FloatingPoint(bb); - case 2: // Time - throw new UnsupportedHdfException("Time data type is not yet supported"); + case TimeDataType.CLASS_ID: // Time + return new TimeDataType(bb); case StringData.CLASS_ID: // String return new StringData(bb); case BitField.CLASS_ID: // Bit field diff --git a/jhdf/src/main/java/io/jhdf/object/datatype/TimeDataType.java b/jhdf/src/main/java/io/jhdf/object/datatype/TimeDataType.java new file mode 100644 index 00000000..e873c9dd --- /dev/null +++ b/jhdf/src/main/java/io/jhdf/object/datatype/TimeDataType.java @@ -0,0 +1,72 @@ +/* + * This file is part of jHDF. A pure Java library for accessing HDF5 files. + * + * https://jhdf.io + * + * Copyright (c) 2025 James Mudd + * + * MIT License see 'LICENSE' file + */ +package io.jhdf.object.datatype; + +import io.jhdf.storage.HdfBackingStorage; + +import java.lang.reflect.Array; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import static io.jhdf.Utils.stripLeadingIndex; + +public class TimeDataType extends DataType implements OrderedDataType { + public static final int CLASS_ID = 2; + + private final ByteOrder order; + private final short bitPrecision; + + public TimeDataType(ByteBuffer bb) { + super(bb); + + if (classBits.get(0)) { + order = ByteOrder.BIG_ENDIAN; + } else { + order = ByteOrder.LITTLE_ENDIAN; + } + + bitPrecision = bb.getShort(); + } + + @Override + public ByteOrder getByteOrder() { + return order; + } + @Override + public Class getJavaType() { + return byte[].class; + } + + @Override + public Object fillData(ByteBuffer buffer, int[] dimensions, HdfBackingStorage hdfBackingStorage) { + final Object data = Array.newInstance(getJavaType(), dimensions); + fillData(data, dimensions, buffer.order(getByteOrder())); + return data; + } + + private void fillData(Object data, int[] dims, ByteBuffer buffer) { + if (dims.length > 1) { + for (int i = 0; i < dims[0]; i++) { + Object newArray = Array.get(data, i); + fillData(newArray, stripLeadingIndex(dims), buffer); + } + } else { + for (int i = 0; i < Array.getLength(data); i++) { + byte[] bytes = new byte[getSize()]; + buffer.get(bytes); + Array.set(data, i, bytes); + } + } + } + + public short getBitPrecision() { + return bitPrecision; + } +} diff --git a/jhdf/src/test/resources/hdf5/isssue-523.hdf5 b/jhdf/src/test/resources/hdf5/isssue-523.hdf5 new file mode 100644 index 00000000..ff8aa906 Binary files /dev/null and b/jhdf/src/test/resources/hdf5/isssue-523.hdf5 differ