Skip to content

Commit c78f371

Browse files
committed
refactor v2 code
1 parent 04700c0 commit c78f371

2 files changed

Lines changed: 95 additions & 51 deletions

File tree

src/main/java/org/hdf5javalib/hdffile/dataobjects/messages/AttributeMessage.java

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -89,48 +89,79 @@ public AttributeMessage(int version, HdfString name, DatatypeMessage datatypeMes
8989
/**
9090
* Parses an AttributeMessage from the provided data and file context.
9191
*
92-
* @param flags message flags
93-
* @param data the byte array containing the message data
94-
* @param hdfDataFile the HDF5 file context for global heap and other resources
92+
* @param messageFlags message flags
93+
* @param data the byte array containing the message data
94+
* @param hdfDataFile the HDF5 file context for global heap and other resources
9595
* @return a new AttributeMessage instance parsed from the data
9696
*/
97-
public static HdfMessage parseHeaderMessage(int flags, byte[] data, HdfDataFile hdfDataFile) throws InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
97+
public static HdfMessage parseHeaderMessage(int messageFlags, byte[] data, HdfDataFile hdfDataFile) throws InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
9898
ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
9999
// Read the version (1 byte)
100100
int version = Byte.toUnsignedInt(buffer.get());
101101

102-
// Skip the reserved byte (1 byte, should be zero)
103-
buffer.get();
104-
105-
// Read the sizes of name, datatype, and dataspace (2 bytes each)
106-
int nameSize = Short.toUnsignedInt(buffer.getShort());
107-
int datatypeSize = Short.toUnsignedInt(buffer.getShort());
108-
int dataspaceSize = Short.toUnsignedInt(buffer.getShort());
109-
110-
// Read the name (variable size)
111-
byte[] nameBytes = new byte[nameSize];
112-
buffer.get(nameBytes);
113-
BitSet bitSet = StringDatatype.createClassBitField(StringDatatype.PaddingType.NULL_TERMINATE, StringDatatype.CharacterSet.ASCII);
114-
HdfString name = new HdfString(nameBytes, new StringDatatype(StringDatatype.createClassAndVersion(), bitSet, nameSize, hdfDataFile));
115-
// get padding bytes
116-
int padding = (8 - (nameSize % 8)) % 8;
117-
byte[] paddingBytes = new byte[padding];
118-
buffer.get(paddingBytes);
119-
120-
byte[] dtBytes = new byte[datatypeSize];
121-
buffer.get(dtBytes);
122-
// get padding bytes
123-
padding = (8 - (datatypeSize % 8)) % 8;
124-
paddingBytes = new byte[padding];
125-
buffer.get(paddingBytes);
126-
127-
byte[] dsBytes = new byte[dataspaceSize];
128-
buffer.get(dsBytes);
129-
// get padding bytes
130-
padding = (8 - (dataspaceSize % 8)) % 8;
131-
paddingBytes = new byte[padding];
132-
buffer.get(paddingBytes);
102+
int nameSize;
103+
int datatypeSize;
104+
int dataspaceSize;
105+
HdfString name;
106+
107+
byte[] dtBytes;
108+
byte[] dsBytes;
109+
110+
if (version == 1) {
111+
// Version 1 requires 8-byte padding between fields.
112+
buffer.get(); // Skip reserved byte
113+
nameSize = Short.toUnsignedInt(buffer.getShort());
114+
datatypeSize = Short.toUnsignedInt(buffer.getShort());
115+
dataspaceSize = Short.toUnsignedInt(buffer.getShort());
116+
117+
byte[] nameBytes = new byte[nameSize];
118+
buffer.get(nameBytes);
119+
BitSet bitSet = StringDatatype.createClassBitField(StringDatatype.PaddingType.NULL_TERMINATE, StringDatatype.CharacterSet.ASCII);
120+
name = new HdfString(nameBytes, new StringDatatype(StringDatatype.createClassAndVersion(), bitSet, nameSize, hdfDataFile));
121+
122+
// Apply 8-byte alignment padding after the name
123+
buffer.position((buffer.position() + 7) & ~7);
124+
125+
dtBytes = new byte[datatypeSize];
126+
buffer.get(dtBytes);
127+
// Apply 8-byte alignment padding after the datatype
128+
buffer.position((buffer.position() + 7) & ~7);
129+
130+
dsBytes = new byte[dataspaceSize];
131+
buffer.get(dsBytes);
132+
// Apply 8-byte alignment padding after the dataspace
133+
buffer.position((buffer.position() + 7) & ~7);
134+
135+
} else if (version == 2 || version == 3) {
136+
// Versions 2 & 3 have NO PADDING between fields.
137+
buffer.get(); // Read flags (for v3) or reserved byte (for v2)
138+
nameSize = Short.toUnsignedInt(buffer.getShort());
139+
datatypeSize = Short.toUnsignedInt(buffer.getShort());
140+
dataspaceSize = Short.toUnsignedInt(buffer.getShort());
141+
142+
StringDatatype.CharacterSet characterSet = StringDatatype.CharacterSet.ASCII;
143+
if (version == 3) {
144+
byte charSetByte = buffer.get();
145+
characterSet = (charSetByte == 0) ? StringDatatype.CharacterSet.ASCII : StringDatatype.CharacterSet.UTF8;
146+
}
147+
148+
byte[] nameBytes = new byte[nameSize];
149+
buffer.get(nameBytes);
150+
BitSet bitSet = StringDatatype.createClassBitField(StringDatatype.PaddingType.NULL_TERMINATE, characterSet);
151+
name = new HdfString(nameBytes, new StringDatatype(StringDatatype.createClassAndVersion(), bitSet, nameSize, hdfDataFile));
152+
153+
// Read fields sequentially with no padding
154+
dtBytes = new byte[datatypeSize];
155+
buffer.get(dtBytes);
156+
157+
dsBytes = new byte[dataspaceSize];
158+
buffer.get(dsBytes);
133159

160+
} else {
161+
throw new IOException("Unsupported AttributeMessage version: " + version);
162+
}
163+
164+
// --- (This section is restored to your original code) ---
134165
HdfMessage hdfDataObjectHeaderDt = parseHeaderMessage(MessageType.DATATYPE_MESSAGE, (byte) 0, dtBytes, hdfDataFile);
135166
DatatypeMessage dt = (DatatypeMessage) hdfDataObjectHeaderDt;
136167
HdfMessage hdfDataObjectHeaderDs = parseHeaderMessage(MessageType.DATASPACE_MESSAGE, (byte) 0, dsBytes, hdfDataFile);
@@ -146,7 +177,7 @@ public static HdfMessage parseHeaderMessage(int flags, byte[] data, HdfDataFile
146177
byte[] dataBytes = new byte[dtDataSize];
147178
buffer.get(dataBytes);
148179
HdfData scalarValue = dt.getHdfDatatype().getInstance(HdfData.class, dataBytes);
149-
return new AttributeMessage(version, name, dt, ds, HdfDataHolder.ofScalar(scalarValue), flags, data.length);
180+
return new AttributeMessage(version, name, dt, ds, HdfDataHolder.ofScalar(scalarValue), messageFlags, data.length);
150181
}
151182

152183
// Case 2: Array data (dimensionality is 1 or more)
@@ -160,15 +191,12 @@ public static HdfMessage parseHeaderMessage(int flags, byte[] data, HdfDataFile
160191
dimensions = Arrays.copyOfRange(dimensions, 0, count);
161192

162193
// Step 1: Create the n-dimensional array dynamically.
163-
// Array.newInstance() is the key. It can create an array of any type with any dimensions.
164-
// Example: Array.newInstance(HdfData.class, 2, 3) creates a HdfData[2][3]
165194
Object multiDimArray = Array.newInstance(HdfData.class, dimensions);
166195

167196
// Step 2: Populate the array recursively from the flat buffer.
168197
populateArray(multiDimArray, dimensions, 0, buffer, dt.getHdfDatatype(), dtDataSize);
169198

170-
return new AttributeMessage(version, name, dt, ds, HdfDataHolder.ofArray(multiDimArray, dimensions), flags, data.length);
171-
199+
return new AttributeMessage(version, name, dt, ds, HdfDataHolder.ofArray(multiDimArray, dimensions), messageFlags, data.length);
172200
}
173201

174202
/**

src/main/java/org/hdf5javalib/hdffile/dataobjects/messages/DataspaceMessage.java

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,28 +94,46 @@ public DataspaceMessage(
9494
/**
9595
* Parses a DataspaceMessage from the provided data and file context.
9696
*
97-
* @param flags message flags
98-
* @param data the byte array containing the message data
99-
* @param hdfDataFile the HDF5 file context for datatype resources
97+
* @param messageFlags message flags
98+
* @param data the byte array containing the message data
99+
* @param hdfDataFile the HDF5 file context for datatype resources
100100
* @return a new DataspaceMessage instance parsed from the data
101101
*/
102-
public static HdfMessage parseHeaderMessage(int flags, byte[] data, HdfDataFile hdfDataFile) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
102+
public static HdfMessage parseHeaderMessage(int messageFlags, byte[] data, HdfDataFile hdfDataFile) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
103103
ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
104104

105105
int version = Byte.toUnsignedInt(buffer.get());
106-
int dimensionality = Byte.toUnsignedInt(buffer.get());
107-
int flagByte = Byte.toUnsignedInt(buffer.get());
108-
BitSet flagSet = BitSet.valueOf(new byte[]{(byte) flagByte});
106+
int dimensionality;
107+
BitSet flagSet;
108+
109109
if (version == 1) {
110+
dimensionality = Byte.toUnsignedInt(buffer.get());
111+
byte flagByte = buffer.get();
112+
flagSet = BitSet.valueOf(new byte[]{flagByte});
113+
// Version 1 has 5 reserved bytes that must be skipped.
110114
buffer.position(buffer.position() + DATASPACE_MESSAGE_RESERVED_1);
111-
} else {
115+
116+
} else if (version == 2) {
117+
dimensionality = Byte.toUnsignedInt(buffer.get());
118+
byte flagByte = buffer.get();
119+
flagSet = BitSet.valueOf(new byte[]{flagByte});
120+
// Version 2 has a 'Type' field here. We must read it to advance the buffer,
121+
// even if we don't use the 'type' value directly.
112122
int type = Byte.toUnsignedInt(buffer.get());
123+
124+
} else {
125+
throw new IOException("Unsupported DataspaceMessage version: " + version);
113126
}
127+
128+
// --- Common logic for reading dimensions ---
129+
// This part now works correctly because the buffer is positioned properly for any supported version.
114130
HdfFixedPoint[] dimensions = new HdfFixedPoint[dimensionality];
115131
for (int i = 0; i < dimensionality; i++) {
116132
dimensions[i] = HdfReadUtils.readHdfFixedPointFromBuffer(hdfDataFile.getSuperblock().getFixedPointDatatypeForLength(), buffer);
117133
}
118134

135+
// The spec states bit 0 of the flags indicates if max dimensions are present.
136+
// Assuming your DataspaceFlag enum handles this correctly.
119137
boolean hasMaxDimensions = flagSet.get(DataspaceFlag.MAX_DIMENSIONS_PRESENT.getBitIndex());
120138
HdfFixedPoint[] maxDimensions = null;
121139
if (hasMaxDimensions) {
@@ -125,9 +143,7 @@ public static HdfMessage parseHeaderMessage(int flags, byte[] data, HdfDataFile
125143
}
126144
}
127145

128-
return new DataspaceMessage(version, dimensionality, flagSet, dimensions, maxDimensions, hasMaxDimensions, flags, data.length);
129-
130-
146+
return new DataspaceMessage(version, dimensionality, flagSet, dimensions, maxDimensions, hasMaxDimensions, messageFlags, data.length);
131147
}
132148

133149
/**

0 commit comments

Comments
 (0)