Skip to content

Commit a1f0039

Browse files
authored
Merge pull request #12981 from rouault/hdf5_multidim_non_default_stride
HDF5 multidim: fix reading array with non-default stride
2 parents 23e8350 + d7932d2 commit a1f0039

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

autotest/gdrivers/hdf5multidim.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,17 @@ def test_hdf5_multidim_read_array():
362362
assert struct.unpack("H" * (len(data) // 2), data) == got_data_ref
363363

364364

365+
def test_hdf5_multidim_read_stride():
366+
367+
ds = gdal.OpenEx("HDF5:data/netcdf/alldatatypes.nc", gdal.OF_MULTIDIM_RASTER)
368+
rg = ds.GetRootGroup()
369+
370+
var = rg.OpenMDArray("ubyte_z2_y2_x2_var")
371+
assert struct.unpack("B" * 119, var.Read(buffer_stride=[3 * 4 * 2, 4 * 2, 1 * 2]))[
372+
::2
373+
] == struct.unpack("B" * 60, var.Read())
374+
375+
365376
def test_hdf5_multidim_attr_alldatatypes():
366377

367378
ds = gdal.OpenEx("HDF5:data/netcdf/alldatatypes.nc", gdal.OF_MULTIDIM_RASTER)

frmts/hdf5/hdf5multidim.cpp

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,8 +2675,22 @@ bool HDF5Array::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
26752675
pDstBuffer);
26762676
}
26772677

2678+
bool strideOK = true;
2679+
GPtrDiff_t nExpectedBufferStride = 1;
2680+
for (size_t i = nDims; i != 0;)
2681+
{
2682+
--i;
2683+
if (count[i] != 1 && bufferStride[i] != nExpectedBufferStride)
2684+
{
2685+
strideOK = false;
2686+
break;
2687+
}
2688+
nExpectedBufferStride *= count[i];
2689+
}
2690+
26782691
hid_t hBufferType = H5I_INVALID_HID;
26792692
GByte *pabyTemp = nullptr;
2693+
bool bUseTmpBuffer = false;
26802694
if (m_dt.GetClass() == GEDTC_STRING)
26812695
{
26822696
if (bufferDataType.GetClass() != GEDTC_STRING)
@@ -2693,7 +2707,7 @@ bool HDF5Array::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
26932707
return false;
26942708
}
26952709
}
2696-
else if (bufferDataType.GetClass() == GEDTC_NUMERIC &&
2710+
else if (strideOK && bufferDataType.GetClass() == GEDTC_NUMERIC &&
26972711
m_dt.GetClass() == GEDTC_NUMERIC &&
26982712
!GDALDataTypeIsComplex(m_dt.GetNumericDataType()) &&
26992713
!GDALDataTypeIsComplex(bufferDataType.GetNumericDataType()))
@@ -2715,14 +2729,7 @@ bool HDF5Array::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
27152729
hBufferType = H5Tcopy(m_hNativeDT);
27162730
if (m_dt != bufferDataType)
27172731
{
2718-
const size_t nDataTypeSize = H5Tget_size(m_hNativeDT);
2719-
pabyTemp = static_cast<GByte *>(
2720-
VSI_MALLOC2_VERBOSE(nDataTypeSize, nEltCount));
2721-
if (pabyTemp == nullptr)
2722-
{
2723-
H5Tclose(hBufferType);
2724-
return false;
2725-
}
2732+
bUseTmpBuffer = true;
27262733
}
27272734
}
27282735
H5Tclose(hParent);
@@ -2733,24 +2740,33 @@ bool HDF5Array::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
27332740
bufferDataType);
27342741
if (hBufferType == H5I_INVALID_HID)
27352742
{
2736-
VSIFree(pabyTemp);
27372743
return false;
27382744
}
27392745
}
27402746
}
2741-
else
2747+
else if (strideOK)
27422748
{
27432749
hBufferType = H5Tcopy(m_hNativeDT);
27442750
if (m_dt != bufferDataType || m_bHasString || m_bHasNonNativeDataType)
27452751
{
2746-
const size_t nDataTypeSize = H5Tget_size(m_hNativeDT);
2747-
pabyTemp = static_cast<GByte *>(
2748-
VSI_MALLOC2_VERBOSE(nDataTypeSize, nEltCount));
2749-
if (pabyTemp == nullptr)
2750-
{
2751-
H5Tclose(hBufferType);
2752-
return false;
2753-
}
2752+
bUseTmpBuffer = true;
2753+
}
2754+
}
2755+
else
2756+
{
2757+
hBufferType = H5Tcopy(m_hNativeDT);
2758+
bUseTmpBuffer = true;
2759+
}
2760+
2761+
if (bUseTmpBuffer)
2762+
{
2763+
const size_t nDataTypeSize = H5Tget_size(hBufferType);
2764+
pabyTemp =
2765+
static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nDataTypeSize, nEltCount));
2766+
if (pabyTemp == nullptr)
2767+
{
2768+
H5Tclose(hBufferType);
2769+
return false;
27542770
}
27552771
}
27562772

0 commit comments

Comments
 (0)