reader: a one-element string array is a scalar
Masters exist that store sensor_material, description and the compression name as shape (1,) rather than as true scalars - JUNGFRAU files from an early beamline deployment do, and the application definition permits it. ReadString() required rank 0 and threw on anything else, so the whole file was lost: the metadata parse never finished and no image was ever examined. Accept any shape holding exactly one element, and keep throwing for a string dataset that genuinely holds several, which is a different quantity and cannot be read into one std::string. The numeric path already worked this way (HDF5DataSet_scalar_stored_rank1); this is the string half. Measured: three long-wavelength rotation datasets that could not be opened at all now process end to end. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
This commit is contained in:
1 parent
680c36c20d
commit
c77ebe56c3
2 files changed
+33
-2
No files matched your search
@@ -137,6 +137,26 @@ TEST_CASE("HDF5DataSet_string", "[HDF5][Unit]") {
|
||||
REQUIRE (H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("HDF5DataSet_string_stored_rank1", "[HDF5][Unit]") {
|
||||
// Facilities write a one-element string array where the application definition allows a scalar -
|
||||
// JUNGFRAU masters from an early beamline deployment store sensor_material and description that
|
||||
// way - and the file is unreadable if that is refused, because the metadata parse never finishes.
|
||||
{
|
||||
HDF5File file("scratch2b.h5");
|
||||
file.SaveVector("one", std::vector<std::string>{"Si"});
|
||||
file.SaveVector("two", std::vector<std::string>{"Si", "CdTe"});
|
||||
}
|
||||
{
|
||||
HDF5ReadOnlyFile file("scratch2b.h5");
|
||||
HDF5DataSet one(file, "one");
|
||||
CHECK(HDF5DataSpace(one).GetNumOfDimensions() == 1);
|
||||
CHECK(one.ReadString() == "Si");
|
||||
REQUIRE_THROWS(HDF5DataSet(file, "two").ReadString());
|
||||
}
|
||||
remove("scratch2b.h5");
|
||||
REQUIRE (H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("HDF5DataSet_vector", "[HDF5][Unit]") {
|
||||
std::vector<double> tmp_vector (16384);
|
||||
tmp_vector[0] = 599.88;
|
||||
|
||||
+13
-2
@@ -908,8 +908,19 @@ HDF5DataSet& HDF5DataSet::WriteDirectChunk(const void *data, hsize_t data_size,
|
||||
|
||||
std::string HDF5DataSet::ReadString() const {
|
||||
HDF5DataSpace file_space(*this);
|
||||
if (file_space.GetNumOfDimensions() != 0)
|
||||
throw JFJochException(JFJochExceptionCategory::HDF5, "Dataset tries to read string (scalar) from vector dataset");
|
||||
// A rank-1 dataset holding exactly one string is the same thing as a scalar, and facilities
|
||||
// write it both ways - JUNGFRAU masters from an early beamline deployment store
|
||||
// sensor_material and description as shape (1,). Refusing those loses the whole file over a
|
||||
// difference that carries no information.
|
||||
if (file_space.GetNumOfDimensions() != 0) {
|
||||
const auto dims = file_space.GetDimensions();
|
||||
hsize_t elements = 1;
|
||||
for (const auto d : dims)
|
||||
elements *= d;
|
||||
if (elements != 1)
|
||||
throw JFJochException(JFJochExceptionCategory::HDF5,
|
||||
"Dataset tries to read string (scalar) from vector dataset");
|
||||
}
|
||||
|
||||
HDF5DataType file_data_type(*this);
|
||||
const size_t size = file_data_type.GetElemSize();
|
||||
|
||||
Reference in new issue
Block a user