diff --git a/java/hdf/hdf5lib/H5.java b/java/hdf/hdf5lib/H5.java index c6ee9f198b8..f81f29513ad 100644 --- a/java/hdf/hdf5lib/H5.java +++ b/java/hdf/hdf5lib/H5.java @@ -12495,6 +12495,111 @@ public class H5 implements java.io.Serializable { return H5Pset_filter(plist_id, filter_id, flags, (long)values.length, values); } + /** + * @ingroup JH5P + * + * H5Pmodify_filter_by_idx replaces the configuration of the filter at a pipeline index using a + * human-readable key=value parameter string. The entry keeps a stored configuration string. + * + * @param plist_id + * IN: Property list identifier. + * @param filter_idx + * IN: Zero-based index of the filter in the pipeline. + * @param flags + * IN: Bit vector specifying certain general properties of the filter. + * @param params + * IN: Parameter string in "key=value" format, or null for no parameters. + * + * @return a non-negative value if successful + * + * @exception HDF5LibraryException + * Error from the HDF5 Library. + **/ + public static int H5Pmodify_filter_by_idx(long plist_id, int filter_idx, int flags, String params) + throws HDF5LibraryException + { + if (plist_id < 0) + throw new HDF5FunctionArgumentException("Negative property list identifier"); + + int retVal = -1; + /* H5Z_params_t layout (64-bit): int type(4) + pad(4) + union(16) = 24 bytes */ + final int H5Z_PARAMS_STRING = 1; + try (Arena arena = Arena.ofConfined()) { + MemorySegment str_seg = + (params != null && !params.isEmpty()) ? arena.allocateFrom(params) : MemorySegment.NULL; + MemorySegment params_struct = arena.allocate(24, 8); + params_struct.set(ValueLayout.JAVA_INT, 0, H5Z_PARAMS_STRING); + params_struct.set(ValueLayout.ADDRESS, 8, str_seg); + retVal = org.hdfgroup.javahdf5.hdf5_h.H5Pmodify_filter_by_idx(plist_id, filter_idx, flags, + params_struct); + } + catch (HDF5LibraryException e) { + throw e; + } + catch (Throwable t) { + throw new HDF5LibraryException("H5Pmodify_filter_by_idx failed: " + t.getMessage()); + } + if (retVal < 0) + h5libraryError(); + return retVal; + } + + /** + * @ingroup JH5P + * + * H5Pmodify_filter_by_idx replaces the configuration of the filter at a pipeline index using raw + * cd_values parameters. This form clears any stored configuration string on the entry, so + * introspection falls back to the filter's get_config reconstruction. + * + * @param plist_id + * IN: Property list identifier. + * @param filter_idx + * IN: Zero-based index of the filter in the pipeline. + * @param flags + * IN: Bit vector specifying certain general properties of the filter. + * @param cd_values + * IN: Auxiliary data for the filter, or null for no parameters. + * + * @return a non-negative value if successful + * + * @exception HDF5LibraryException + * Error from the HDF5 Library. + **/ + public static int H5Pmodify_filter_by_idx(long plist_id, int filter_idx, int flags, int[] cd_values) + throws HDF5LibraryException + { + if (plist_id < 0) + throw new HDF5FunctionArgumentException("Negative property list identifier"); + + int retVal = -1; + /* Unlike the append case this cannot delegate to H5Pmodify_filter: that + * addresses an entry by filter ID and resolves to the first match, whereas + * this API addresses by pipeline index. The struct is built explicitly. */ + final int H5Z_PARAMS_CDVALUES = 0; + int[] values = (cd_values != null) ? cd_values : new int[0]; + try (Arena arena = Arena.ofConfined()) { + MemorySegment vals_seg = (values.length > 0) + ? arena.allocateFrom(ValueLayout.JAVA_INT, values) + : MemorySegment.NULL; + MemorySegment params_struct = arena.allocate(24, 8); + params_struct.set(ValueLayout.JAVA_INT, 0, H5Z_PARAMS_CDVALUES); + /* union { struct { size_t cd_nelmts; const unsigned *cd_values; } raw; ... } */ + params_struct.set(ValueLayout.JAVA_LONG, 8, (long)values.length); + params_struct.set(ValueLayout.ADDRESS, 16, vals_seg); + retVal = org.hdfgroup.javahdf5.hdf5_h.H5Pmodify_filter_by_idx(plist_id, filter_idx, flags, + params_struct); + } + catch (HDF5LibraryException e) { + throw e; + } + catch (Throwable t) { + throw new HDF5LibraryException("H5Pmodify_filter_by_idx failed: " + t.getMessage()); + } + if (retVal < 0) + h5libraryError(); + return retVal; + } + /** * @ingroup JH5P * diff --git a/java/src-jni/hdf/hdf5lib/H5.java b/java/src-jni/hdf/hdf5lib/H5.java index e8b9099a265..337f6436783 100644 --- a/java/src-jni/hdf/hdf5lib/H5.java +++ b/java/src-jni/hdf/hdf5lib/H5.java @@ -8500,6 +8500,67 @@ public class H5 implements java.io.Serializable { private synchronized static native int H5Pappend_filter_raw(long plist_id, int filter_id, int flags, int[] cd_values) throws HDF5LibraryException; + /** + * @ingroup JH5P + * + * H5Pmodify_filter_by_idx replaces the configuration of the filter at a pipeline index using a + * human-readable key=value parameter string. The entry keeps a stored configuration string. + * + * @param plist_id + * IN: Property list identifier. + * @param filter_idx + * IN: Zero-based index of the filter in the pipeline. + * @param flags + * IN: Bit vector specifying general filter properties. + * @param params + * IN: Parameter string in "key=value" format, or null for no parameters. + * + * @return a non-negative value if successful + * + * @exception HDF5LibraryException + * Error from the HDF5 Library. + **/ + public synchronized static int H5Pmodify_filter_by_idx(long plist_id, int filter_idx, int flags, + String params) throws HDF5LibraryException + { + return H5Pmodify_filter_by_idx_str(plist_id, filter_idx, flags, params); + } + + private synchronized static native int H5Pmodify_filter_by_idx_str(long plist_id, int filter_idx, + int flags, String params) + throws HDF5LibraryException; + + /** + * @ingroup JH5P + * + * H5Pmodify_filter_by_idx replaces the configuration of the filter at a pipeline index using raw + * cd_values parameters. This form clears any stored configuration string on the entry, so + * introspection falls back to the filter's get_config reconstruction. + * + * @param plist_id + * IN: Property list identifier. + * @param filter_idx + * IN: Zero-based index of the filter in the pipeline. + * @param flags + * IN: Bit vector specifying general filter properties. + * @param cd_values + * IN: Auxiliary data for the filter, or null for no parameters. + * + * @return a non-negative value if successful + * + * @exception HDF5LibraryException + * Error from the HDF5 Library. + **/ + public synchronized static int H5Pmodify_filter_by_idx(long plist_id, int filter_idx, int flags, + int[] cd_values) throws HDF5LibraryException + { + return H5Pmodify_filter_by_idx_raw(plist_id, filter_idx, flags, cd_values); + } + + private synchronized static native int H5Pmodify_filter_by_idx_raw(long plist_id, int filter_idx, + int flags, int[] cd_values) + throws HDF5LibraryException; + /** * @ingroup JH5P * diff --git a/java/src-jni/jni/h5pDCPLImp.c b/java/src-jni/jni/h5pDCPLImp.c index ace00f49cf4..bf2a1323701 100644 --- a/java/src-jni/jni/h5pDCPLImp.c +++ b/java/src-jni/jni/h5pDCPLImp.c @@ -1458,6 +1458,78 @@ done: return (jint)status; } /* end Java_hdf_hdf5lib_H5_H5Pappend_1filter_1raw */ +/* + * Class: hdf_hdf5lib_H5 + * Method: H5Pmodify_filter_by_idx (string form) + * Signature: (JIILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL +Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1str(JNIEnv *env, jclass clss, jlong plist_id, + jint filter_idx, jint flags, jstring params) +{ + H5Z_params_t p; + const char *c_params = NULL; + jboolean isCopy; + herr_t status = FAIL; + + UNUSED(clss); + + if (params) + PIN_JAVA_STRING(ENVONLY, params, c_params, &isCopy, + "H5Pmodify_filter_by_idx: params string not pinned"); + + p.type = H5Z_PARAMS_STRING; + p.u.str = c_params; + + if ((status = H5Pmodify_filter_by_idx((hid_t)plist_id, (unsigned)filter_idx, (unsigned)flags, &p)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + +done: + if (c_params) + UNPIN_JAVA_STRING(ENVONLY, params, c_params); + + return (jint)status; +} /* end Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1str */ + +/* + * Class: hdf_hdf5lib_H5 + * Method: H5Pmodify_filter_by_idx (raw cd_values form) + * Signature: (JII[I)I + */ +JNIEXPORT jint JNICALL +Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1raw(JNIEnv *env, jclass clss, jlong plist_id, + jint filter_idx, jint flags, jintArray cd_values) +{ + H5Z_params_t p; + jint *c_cd_values = NULL; + jboolean isCopy; + herr_t status = FAIL; + jsize cd_nelmts = 0; + + UNUSED(clss); + + if (cd_values) { + cd_nelmts = ENVPTR->GetArrayLength(ENVONLY, cd_values); + if (cd_nelmts < 0) + H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Pmodify_filter_by_idx: cd_values array length < 0"); + PIN_INT_ARRAY(ENVONLY, cd_values, c_cd_values, &isCopy, + "H5Pmodify_filter_by_idx: cd_values not pinned"); + } + + p.type = H5Z_PARAMS_CDVALUES; + p.u.raw.cd_nelmts = (size_t)cd_nelmts; + p.u.raw.cd_values = (const unsigned *)c_cd_values; + + if ((status = H5Pmodify_filter_by_idx((hid_t)plist_id, (unsigned)filter_idx, (unsigned)flags, &p)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + +done: + if (c_cd_values) + UNPIN_INT_ARRAY(ENVONLY, cd_values, c_cd_values, JNI_ABORT); + + return (jint)status; +} /* end Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1raw */ + /* * Class: hdf_hdf5lib_H5 * Method: H5Pget_filter_params_by_idx diff --git a/java/src-jni/jni/h5pDCPLImp.h b/java/src-jni/jni/h5pDCPLImp.h index 7da678923d0..596924a45e3 100644 --- a/java/src-jni/jni/h5pDCPLImp.h +++ b/java/src-jni/jni/h5pDCPLImp.h @@ -155,6 +155,22 @@ JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Pappend_1filter_1str(JNIEnv *, jcla JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Pappend_1filter_1raw(JNIEnv *, jclass, jlong, jint, jint, jintArray); +/* + * Class: hdf_hdf5lib_H5 + * Method: H5Pmodify_filter_by_idx (string form) + * Signature: (JIILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1str(JNIEnv *, jclass, jlong, jint, + jint, jstring); + +/* + * Class: hdf_hdf5lib_H5 + * Method: H5Pmodify_filter_by_idx (raw cd_values form) + * Signature: (JII[I)I + */ +JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Pmodify_1filter_1by_1idx_1raw(JNIEnv *, jclass, jlong, jint, + jint, jintArray); + /* * Class: hdf_hdf5lib_H5 * Method: H5Pget_filter_params_by_idx diff --git a/java/test/TestH5Z.java b/java/test/TestH5Z.java index 9843bdc5417..47a4afbb82e 100644 --- a/java/test/TestH5Z.java +++ b/java/test/TestH5Z.java @@ -243,6 +243,92 @@ public class TestH5Z { } } + @Test + public void testH5Pmodify_filter_by_idx_string() + { + long dcpl_id = HDF5Constants.H5I_INVALID_HID; + try { + dcpl_id = H5.H5Pcreate(HDF5Constants.H5P_DATASET_CREATE); + assertTrue("H5Pcreate", dcpl_id >= 0); + + if (1 == H5.H5Zfilter_avail(HDF5Constants.H5Z_FILTER_DEFLATE)) { + int ret = H5.H5Pappend_filter(dcpl_id, HDF5Constants.H5Z_FILTER_DEFLATE, 0, "level=1"); + assertTrue("H5Pappend_filter (string, deflate)", ret >= 0); + + // Replace the configuration in place; position and ID are unchanged. + ret = H5.H5Pmodify_filter_by_idx(dcpl_id, 0, 0, "level=9"); + assertTrue("H5Pmodify_filter_by_idx (string)", ret >= 0); + + int nfilters = H5.H5Pget_nfilters(dcpl_id); + assertEquals("nfilters after H5Pmodify_filter_by_idx", 1, nfilters); + + // The entry keeps a stored string, which reports the new value. + String[] params = new String[1]; + ret = H5.H5Pget_filter_params_by_idx(dcpl_id, 0, params); + assertTrue("H5Pget_filter_params_by_idx", ret >= 0); + assertNotNull("params[0] is non-null", params[0]); + assertTrue("stored string reflects the modify: " + params[0], + params[0].contains("level=9")); + } + } + catch (Throwable err) { + err.printStackTrace(); + fail("testH5Pmodify_filter_by_idx_string: " + err); + } + finally { + if (dcpl_id != HDF5Constants.H5I_INVALID_HID) + try { + H5.H5Pclose(dcpl_id); + } + catch (Exception e) { /* ignore */ + } + } + } + + @Test + public void testH5Pmodify_filter_by_idx_cdvalues() + { + long dcpl_id = HDF5Constants.H5I_INVALID_HID; + try { + dcpl_id = H5.H5Pcreate(HDF5Constants.H5P_DATASET_CREATE); + assertTrue("H5Pcreate", dcpl_id >= 0); + + if (1 == H5.H5Zfilter_avail(HDF5Constants.H5Z_FILTER_DEFLATE)) { + int ret = H5.H5Pappend_filter(dcpl_id, HDF5Constants.H5Z_FILTER_DEFLATE, 0, "level=1"); + assertTrue("H5Pappend_filter (string, deflate)", ret >= 0); + + int[] cd_values = new int[] {6}; + ret = H5.H5Pmodify_filter_by_idx(dcpl_id, 0, 0, cd_values); + assertTrue("H5Pmodify_filter_by_idx (cd_values)", ret >= 0); + + int nfilters = H5.H5Pget_nfilters(dcpl_id); + assertEquals("nfilters after H5Pmodify_filter_by_idx", 1, nfilters); + + // cd_values were replaced. + int[] cd_out = new int[1]; + int[] flags_out = new int[1]; + long[] cd_nelmts = new long[] {1}; + String[] name_out = new String[] {""}; + int filter_id = + H5.H5Pget_filter(dcpl_id, 0, flags_out, cd_nelmts, cd_out, 256, name_out, new int[1]); + assertEquals("filter id unchanged by modify", HDF5Constants.H5Z_FILTER_DEFLATE, filter_id); + assertEquals("cd_values[0] after modify", 6, cd_out[0]); + } + } + catch (Throwable err) { + err.printStackTrace(); + fail("testH5Pmodify_filter_by_idx_cdvalues: " + err); + } + finally { + if (dcpl_id != HDF5Constants.H5I_INVALID_HID) + try { + H5.H5Pclose(dcpl_id); + } + catch (Exception e) { /* ignore */ + } + } + } + @Test public void testH5Pget_filter_params_by_idx() { diff --git a/java/test/testfiles/JUnit-TestH5Z.txt b/java/test/testfiles/JUnit-TestH5Z.txt index 831ccb76f42..282e4993129 100644 --- a/java/test/testfiles/JUnit-TestH5Z.txt +++ b/java/test/testfiles/JUnit-TestH5Z.txt @@ -2,6 +2,8 @@ JUnit version 4.13.2 .testH5Pappend_filter_cdvalues .testH5Pappend_filter_string .testH5Pget_filter_params_by_idx +.testH5Pmodify_filter_by_idx_cdvalues +.testH5Pmodify_filter_by_idx_string .testH5Zconfig_get_param_bool .testH5Zconfig_get_param_double .testH5Zconfig_get_param_int @@ -15,5 +17,5 @@ JUnit version 4.13.2 Time: XXXX -OK (13 tests) +OK (15 tests)