mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-25 04:09:44 +03:00
Fix bad reads of nested cmpd/vlen types in JNI (#6413)
* Fix H5DreadVL failing for pre-allocate cmpd-of-seq dsets * Fix bad vlen of cmpd with null slot read * Fix bad cmpd of cmpd read in java `translate_rbuf`'s H5T_VLEN case had a similar bug where when `found_jList` was set to false due to an entyr in `ret_buf` being null, `ret_buf.add()` would be invoked on an array of objects without the list .add() method. This would occur whenever a read was invoked of a vlen sequence with a null (non-preallocated) entry. The pre-existing tests only tested the pre-allocated cases. I removed the use of the `found_jList` flag, since it conflated the passing of an unallocated slot with `ret_buf` not being an array. Instead use `ret_buflen == 0` as the check to match the pattern in H5T_INTEGER and other branches. The test for this fix is testH5Dread_vlen_of_compound_nullslot. --- `translate_atomic_rebuf` had two issues related to handling of nested compounds. First, it discarded recursive returns, resulting in the construction of empty lists. Secondly, its member offset (`char_buf + i * typeSize + memb_offset`) was incorrect. In this case, `i` was the member index and `memberSize` was the entire cmpd size, so the offset would be erroneously large. It seems like this came from copying of the offset computation from `translate_rbuf`, which had to advance over entire elements of compound data. This error was duplicated on the write side in `translate_atomic_wbuf`'s H5T_COMPOUND case (h5util.c:4611). I changed `translate_atomic_rbuf` to capture the resultant object, and dropped the `i * typeSize` term in both routines. The new test verifying the fix works is `testH5Dread_vlen_of_nested_compound`. * Add exception checks * Update NULL checks in translate_wbuf * Correct potentially bad array length check * Clang format * Fix readVL/writeVL crash on malformed buffer * Committing clang-format changes * Add bufSize checks to wbuf/rbuf translation * Remove vlen pre-allocation support * Harden JNI buffer interface * Handle opaque types as byte[] and document JNI buffer data model Opaque elements were grouped with H5T_INTEGER in the nested-type translation path, which boxed them as Integer/Long and rejected arbitrary-sized opaque blobs. Treat H5T_OPAQUE like H5T_REFERENCE (a byte[] per element) in translate_atomic_rbuf, translate_atomic_wbuf, and h5validate_atomic_wbuf so nested opaque round-trips correctly. Also add "Buffer data model" header comments on translate_rbuf() and translate_wbuf() and note the reference/opaque byte[] leaves in the H5.java javadocv. * Initialize typeSize to fix -Werror=maybe-uninitialized typeSize was assigned only inside the vl_data_class branch but read in a second, separate vl_data_class branch, which gcc -O2 flags as maybe-uninitialized under -Werror. Initialize it to 0 at declaration in H5Aread/H5Awrite/H5Dread/H5Dwrite, matching the existing vl_array_len pattern. * Port nested cmpd/vlen tests to java/test and sync reference The legacy java/test tree's JUnit-TestH5D.txt reference listed the new nested compound/vlen tests, but the corresponding @Test methods existed only in java/src-jni/test/TestH5D.java. Port the 10 tests and the writeCompoundOfVlenDataset helper into java/test/TestH5D.java, remove debug prints, and regenerate the reference to match the actual JUnit output. * Support nested vlen/compound datatypes in Java FFM compat layer The FFM compatibility layer (java/hdf) lacked the vlen/compound read and write support that the JNI interface gained, so the nested cmpd/vlen tests ported into java/test (TestH5D) failed and leaked an id. VLDataConverter now has recursive encodeValue/decodeValue helpers that pack and unpack any member class (integer, float, fixed/vl string, nested compound, and VLEN) in the native HDF5 in-memory layout. These are wired into convertCompoundDatatype, readCompoundDatatype and convertRawDataToArrayList, and a type-aware convertToHVLAuto handles top-level VLEN-of-compound writes. Compound reads now reclaim VL memory, and type/count mismatches raise IllegalArgumentException instead of silently corrupting data. H5DwriteVL rejects an undersized buffer up front and routes VLEN writes through convertToHVLAuto. The JUnit-TestH5D reference regains its trailing blank line to match the actual JUnit output. * Committing clang-format changes --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@@ -194,6 +194,22 @@ import org.slf4j.LoggerFactory;
|
||||
* and the parameter <i>data</i> can be any multi-dimensional array of numbers, such as float[][], or
|
||||
* int[][][], or Double[][].
|
||||
* <p>
|
||||
* <b>Buffer data model</b>
|
||||
* <p>
|
||||
* Read/write buffers must match the memory datatype. The JNI verifies this at the API boundary and throws
|
||||
* IllegalArgumentException on a mismatch instead of crashing. The expected Java buffer per datatype class is:
|
||||
* <ul>
|
||||
* <li>integer/enum/bitfield, float: a primitive array (byte/short/int/long/float/double[]) or byte[]; it must
|
||||
* be large enough to hold one element of the memory type per selected point.</li>
|
||||
* <li>fixed- or variable-length string, reference: a String[] (byte[] for references) with one slot per
|
||||
* selected point.</li>
|
||||
* <li>compound, variable-length sequence, array, complex: an Object[] of nested java.util.ArrayLists. Each
|
||||
* element is an ArrayList; a compound is an ArrayList of its members in order, a VLEN/array/complex is an
|
||||
* ArrayList of its elements, and scalar leaves are the boxed type (Integer, Double, String, ...) except
|
||||
* reference and opaque leaves, which are a byte[] holding the element's raw bytes. Slots are
|
||||
* not pre-allocated by the caller on read.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* <b>@ref HDF5CONST</b>
|
||||
* <p>
|
||||
* The HDF5 API defines a set of constants and enumerated values. Most of these values are available to Java
|
||||
@@ -1681,7 +1697,8 @@ public class H5 implements java.io.Serializable {
|
||||
* @param mem_type_id
|
||||
* IN: Identifier of the attribute datatype (in memory).
|
||||
* @param buf
|
||||
* Buffer of variable-lenght to store data read from the file.
|
||||
* Object[] (one slot per element) to store the data read; each slot is filled with a nested
|
||||
* ArrayList structure matching mem_type_id (see "Buffer data model" in the class description).
|
||||
*
|
||||
* @return a non-negative value if successful
|
||||
*
|
||||
@@ -2263,7 +2280,8 @@ public class H5 implements java.io.Serializable {
|
||||
* @param mem_type_id
|
||||
* IN: Identifier of the attribute datatype (in memory).
|
||||
* @param buf
|
||||
* IN: Buffer of variable-lenght with data to be written to the file.
|
||||
* IN: Object[] (one slot per element) holding the data to write; each slot must be a nested
|
||||
* ArrayList structure matching mem_type_id (see "Buffer data model" in the class description).
|
||||
*
|
||||
* @return a non-negative value if successful
|
||||
*
|
||||
@@ -3425,7 +3443,9 @@ public class H5 implements java.io.Serializable {
|
||||
* @param xfer_plist_id
|
||||
* Identifier of a transfer property list for this I/O operation.
|
||||
* @param buf
|
||||
* Buffer of variable-lenght to store data read from the file.
|
||||
* Object[] (one slot per selected point) to store the data read; each slot is filled with a
|
||||
* nested ArrayList structure matching mem_type_id (see "Buffer data model" in the class
|
||||
* description). Slots need not be pre-allocated.
|
||||
*
|
||||
* @return a non-negative value if successful
|
||||
*
|
||||
@@ -4145,7 +4165,9 @@ public class H5 implements java.io.Serializable {
|
||||
* @param xfer_plist_id
|
||||
* Identifier of a transfer property list for this I/O operation.
|
||||
* @param buf
|
||||
* Buffer of variable-length with data to be written to the file.
|
||||
* Object[] (one slot per selected point) holding the data to write; each slot must be a nested
|
||||
* ArrayList structure matching mem_type_id (see "Buffer data model" in the class description).
|
||||
* A structural mismatch raises IllegalArgumentException.
|
||||
*
|
||||
* @return a non-negative value if successful
|
||||
*
|
||||
|
||||
+119
-11
@@ -152,8 +152,8 @@ Java_hdf_hdf5lib_H5_H5Aread(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_t
|
||||
jboolean readBufIsCopy;
|
||||
jbyte *readBuf = NULL;
|
||||
hsize_t dims[H5S_MAX_RANK];
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
size_t typeSize;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
size_t typeSize = 0; // Only used by vl_data_class types
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0; // Only used by vl_data_class types
|
||||
htri_t vl_data_class;
|
||||
@@ -167,6 +167,12 @@ Java_hdf_hdf5lib_H5_H5Aread(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_t
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* For fixed-length data the byte buffer must cover the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jbyte), "H5Aread") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((vl_array_len = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0)
|
||||
@@ -195,7 +201,8 @@ Java_hdf_hdf5lib_H5_H5Aread(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_t
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf);
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -239,8 +246,8 @@ Java_hdf_hdf5lib_H5_H5Awrite(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_
|
||||
jboolean writeBufIsCopy;
|
||||
jbyte *writeBuf = NULL;
|
||||
hsize_t dims[H5S_MAX_RANK];
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
size_t typeSize;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
size_t typeSize = 0; // Only used by vl_data_class types
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0; // Only used by vl_data_class types
|
||||
htri_t vl_data_class;
|
||||
@@ -254,6 +261,12 @@ Java_hdf_hdf5lib_H5_H5Awrite(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* For fixed-length data the byte buffer must cover the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jbyte), "H5Awrite") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((vl_array_len = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -281,7 +294,8 @@ Java_hdf_hdf5lib_H5_H5Awrite(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf);
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
}
|
||||
|
||||
if ((status = H5Awrite((hid_t)attr_id, (hid_t)mem_type_id, writeBuf)) < 0)
|
||||
@@ -338,6 +352,12 @@ Java_hdf_hdf5lib_H5_H5Aread_1short(JNIEnv *env, jclass clss, jlong attr_id, jlon
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jshort), "H5Aread_short") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -408,6 +428,11 @@ Java_hdf_hdf5lib_H5_H5Awrite_1short(JNIEnv *env, jclass clss, jlong attr_id, jlo
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, n, sizeof(jshort), "H5Awrite_short") <
|
||||
0)
|
||||
goto done;
|
||||
|
||||
dims[0] = (hsize_t)n;
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -467,6 +492,12 @@ Java_hdf_hdf5lib_H5_H5Aread_1int(JNIEnv *env, jclass clss, jlong attr_id, jlong
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jint), "H5Aread_int") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -537,6 +568,10 @@ Java_hdf_hdf5lib_H5_H5Awrite_1int(JNIEnv *env, jclass clss, jlong attr_id, jlong
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, n, sizeof(jint), "H5Awrite_int") < 0)
|
||||
goto done;
|
||||
|
||||
dims[0] = (hsize_t)n;
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -596,6 +631,12 @@ Java_hdf_hdf5lib_H5_H5Aread_1long(JNIEnv *env, jclass clss, jlong attr_id, jlong
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jlong), "H5Aread_long") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -666,6 +707,10 @@ Java_hdf_hdf5lib_H5_H5Awrite_1long(JNIEnv *env, jclass clss, jlong attr_id, jlon
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, n, sizeof(jlong), "H5Awrite_long") < 0)
|
||||
goto done;
|
||||
|
||||
dims[0] = (hsize_t)n;
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -725,6 +770,12 @@ Java_hdf_hdf5lib_H5_H5Aread_1float(JNIEnv *env, jclass clss, jlong attr_id, jlon
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jfloat), "H5Aread_float") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -795,6 +846,11 @@ Java_hdf_hdf5lib_H5_H5Awrite_1float(JNIEnv *env, jclass clss, jlong attr_id, jlo
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, n, sizeof(jfloat), "H5Awrite_float") <
|
||||
0)
|
||||
goto done;
|
||||
|
||||
dims[0] = (hsize_t)n;
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -854,6 +910,12 @@ Java_hdf_hdf5lib_H5_H5Aread_1double(JNIEnv *env, jclass clss, jlong attr_id, jlo
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (!vl_data_class &&
|
||||
h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
sizeof(jdouble), "H5Aread_double") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -923,6 +985,11 @@ Java_hdf_hdf5lib_H5_H5Awrite_1double(JNIEnv *env, jclass clss, jlong attr_id, jl
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Awrite_double: buf length < 0");
|
||||
}
|
||||
|
||||
/* Verify the buffer is large enough for the attribute. */
|
||||
if (h5a_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)attr_id, n, sizeof(jdouble), "H5Awrite_double") <
|
||||
0)
|
||||
goto done;
|
||||
|
||||
dims[0] = (hsize_t)n;
|
||||
if ((sid = H5Screate_simple(1, dims, NULL)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -984,6 +1051,10 @@ Java_hdf_hdf5lib_H5_H5Aread_1string(JNIEnv *env, jclass clss, jlong attr_id, jlo
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread_string: read buffer length <= 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per element in the attribute. */
|
||||
if (h5a_validate_slot_buf(env, (hid_t)attr_id, n, "H5Aread_string") < 0)
|
||||
goto done;
|
||||
|
||||
if (!(str_len = H5Tget_size((hid_t)mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1049,6 +1120,10 @@ Java_hdf_hdf5lib_H5_H5Awrite_1string(JNIEnv *env, jclass clss, jlong attr_id, jl
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Awrite_string: write buffer length <= 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per element in the attribute. */
|
||||
if (h5a_validate_slot_buf(env, (hid_t)attr_id, n, "H5Awrite_string") < 0)
|
||||
goto done;
|
||||
|
||||
if (!(str_len = H5Tget_size((hid_t)mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1107,6 +1182,7 @@ Java_hdf_hdf5lib_H5_H5AreadVL(JNIEnv *env, jclass clss, jlong attr_id, jlong mem
|
||||
size_t typeSize;
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0;
|
||||
hssize_t npoints;
|
||||
htri_t vl_data_class;
|
||||
herr_t status = FAIL;
|
||||
htri_t is_variable = 0;
|
||||
@@ -1124,6 +1200,12 @@ Java_hdf_hdf5lib_H5_H5AreadVL(JNIEnv *env, jclass clss, jlong attr_id, jlong mem
|
||||
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* The buffer must hold at least one slot per point in the attribute. */
|
||||
if ((npoints = h5a_io_npoints(env, (hid_t)attr_id)) < 0)
|
||||
goto done;
|
||||
if ((hssize_t)vl_array_len < npoints)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5AreadVL: read buffer is smaller than the attribute");
|
||||
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1135,7 +1217,7 @@ Java_hdf_hdf5lib_H5_H5AreadVL(JNIEnv *env, jclass clss, jlong attr_id, jlong mem
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf);
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf, (size_t)vl_array_len * typeSize);
|
||||
|
||||
done:
|
||||
if (readBuf) {
|
||||
@@ -1173,6 +1255,7 @@ Java_hdf_hdf5lib_H5_H5AwriteVL(JNIEnv *env, jclass clss, jlong attr_id, jlong me
|
||||
size_t typeSize;
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0;
|
||||
hssize_t npoints;
|
||||
htri_t vl_data_class;
|
||||
herr_t status = FAIL;
|
||||
htri_t is_variable = 0;
|
||||
@@ -1193,16 +1276,27 @@ Java_hdf_hdf5lib_H5_H5AwriteVL(JNIEnv *env, jclass clss, jlong attr_id, jlong me
|
||||
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer holds at least one element per point in the attribute. */
|
||||
if ((npoints = h5a_io_npoints(env, (hid_t)attr_id)) < 0)
|
||||
goto done;
|
||||
if ((hssize_t)vl_array_len < npoints)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5AwriteVL: write buffer is smaller than the attribute");
|
||||
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
if (NULL == (writeBuf = calloc((size_t)vl_array_len, typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Awrite: failed to allocate raw VL write buffer");
|
||||
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf);
|
||||
/* Verify the buffer structure matches mem_type_id before converting it. */
|
||||
if (h5validate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len) < 0)
|
||||
goto done;
|
||||
|
||||
if (NULL == (writeBuf = calloc((size_t)vl_array_len, typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Awrite: failed to allocate raw VL write buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
|
||||
if ((status = H5Awrite((hid_t)attr_id, (hid_t)mem_type_id, writeBuf)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -1250,6 +1344,11 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id,
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Aread_VLStrings: read buffer is NULL");
|
||||
|
||||
/* The buffer must have one slot per element in the attribute. */
|
||||
if (h5a_validate_slot_buf(env, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
"H5Aread_VLStrings") < 0)
|
||||
goto done;
|
||||
|
||||
if ((isStr = H5Tdetect_class((hid_t)mem_type_id, H5T_STRING)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1455,6 +1554,11 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id,
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Awrite_VLStrings: write buffer is NULL");
|
||||
|
||||
/* The buffer must have one slot per element in the attribute. */
|
||||
if (h5a_validate_slot_buf(env, (hid_t)attr_id, ENVPTR->GetArrayLength(ENVONLY, buf),
|
||||
"H5Awrite_VLStrings") < 0)
|
||||
goto done;
|
||||
|
||||
if ((isStr = H5Tdetect_class((hid_t)mem_type_id, H5T_STRING)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1690,6 +1794,10 @@ Java_hdf_hdf5lib_H5_H5Aread_1reg_1ref(JNIEnv *env, jclass clss, jlong attr_id, j
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread_reg_ref: buf length < 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per element in the attribute. */
|
||||
if (h5a_validate_slot_buf(env, (hid_t)attr_id, n, "H5Aread_reg_ref") < 0)
|
||||
goto done;
|
||||
|
||||
if (NULL == (ref_data = (H5R_ref_t *)calloc(1, (size_t)n * sizeof(H5R_ref_t))))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Aread_reg_ref: failed to allocate read buffer");
|
||||
|
||||
|
||||
+121
-59
@@ -176,8 +176,8 @@ Java_hdf_hdf5lib_H5_H5Dread(JNIEnv *env, jclass clss, jlong dataset_id, jlong me
|
||||
jboolean isCriticalPinning)
|
||||
{
|
||||
jboolean readBufIsCopy;
|
||||
jbyte *readBuf = NULL;
|
||||
size_t typeSize;
|
||||
jbyte *readBuf = NULL;
|
||||
size_t typeSize = 0; // Only used by vl_data_class types
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0; // Only used by vl_data_class types
|
||||
htri_t vl_data_class;
|
||||
@@ -191,6 +191,13 @@ Java_hdf_hdf5lib_H5_H5Dread(JNIEnv *env, jclass clss, jlong dataset_id, jlong me
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* For fixed-length data the byte buffer must cover the selection. */
|
||||
if (!vl_data_class &&
|
||||
h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jbyte),
|
||||
"H5Dread") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((vl_array_len = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -222,7 +229,8 @@ Java_hdf_hdf5lib_H5_H5Dread(JNIEnv *env, jclass clss, jlong dataset_id, jlong me
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf);
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -258,7 +266,7 @@ Java_hdf_hdf5lib_H5_H5Dwrite(JNIEnv *env, jclass clss, jlong dataset_id, jlong m
|
||||
{
|
||||
jboolean writeBufIsCopy;
|
||||
jbyte *writeBuf = NULL;
|
||||
size_t typeSize;
|
||||
size_t typeSize = 0; // Only used by vl_data_class types
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len = 0; // Only used by vl_data_class types
|
||||
htri_t vl_data_class;
|
||||
@@ -272,6 +280,13 @@ Java_hdf_hdf5lib_H5_H5Dwrite(JNIEnv *env, jclass clss, jlong dataset_id, jlong m
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* For fixed-length data the byte buffer must cover the selection. */
|
||||
if (!vl_data_class &&
|
||||
h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jbyte),
|
||||
"H5Dwrite") < 0)
|
||||
goto done;
|
||||
|
||||
if (vl_data_class) {
|
||||
/* Get size of data array */
|
||||
if ((vl_array_len = ENVPTR->GetArrayLength(ENVONLY, buf)) < 0) {
|
||||
@@ -299,7 +314,8 @@ Java_hdf_hdf5lib_H5_H5Dwrite(JNIEnv *env, jclass clss, jlong dataset_id, jlong m
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf);
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
}
|
||||
|
||||
if ((status = H5Dwrite((hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
@@ -430,11 +446,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1short(JNIEnv *env, jclass clss, jlong dataset_id, j
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dread_short: read buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jshort),
|
||||
"H5Dread_short") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -487,11 +503,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1short(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_short: write buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jshort),
|
||||
"H5Dwrite_short") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -544,11 +560,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1int(JNIEnv *env, jclass clss, jlong dataset_id, jlo
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dread_int: read buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jint),
|
||||
"H5Dread_int") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -601,11 +617,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1int(JNIEnv *env, jclass clss, jlong dataset_id, jl
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_int: write buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jint),
|
||||
"H5Dwrite_int") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -658,11 +674,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1long(JNIEnv *env, jclass clss, jlong dataset_id, jl
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dread_long: read buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jlong),
|
||||
"H5Dread_long") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -715,11 +731,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1long(JNIEnv *env, jclass clss, jlong dataset_id, j
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_long: write buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jlong),
|
||||
"H5Dwrite_long") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -772,11 +788,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1float(JNIEnv *env, jclass clss, jlong dataset_id, j
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dread_float: read buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jfloat),
|
||||
"H5Dread_float") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -832,11 +848,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1float(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jfloat),
|
||||
"H5Dwrite_float") < 0)
|
||||
goto done;
|
||||
|
||||
if (isCriticalPinning) {
|
||||
PIN_FLOAT_ARRAY_CRITICAL(ENVONLY, buf, writeBuf, &writeBufIsCopy,
|
||||
@@ -886,11 +902,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1double(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dread_double: read buffer is NULL");
|
||||
|
||||
/* Get size of data array */
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Aread: readBuf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jdouble),
|
||||
"H5Dread_double") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -943,10 +959,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1double(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_double: write buffer is NULL");
|
||||
|
||||
if (ENVPTR->GetArrayLength(ENVONLY, buf) < 0) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_double: buf length < 0");
|
||||
}
|
||||
/* Verify the buffer is large enough for the selection. */
|
||||
if (h5d_validate_raw_buf(env, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)dataset_id, ENVPTR->GetArrayLength(ENVONLY, buf), sizeof(jdouble),
|
||||
"H5Dwrite_double") < 0)
|
||||
goto done;
|
||||
|
||||
if ((vl_data_class = h5str_detect_vlen(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -1007,6 +1024,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1string(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread_string: read buffer length <= 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per selected point. */
|
||||
if (h5d_validate_slot_buf(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id, n,
|
||||
"H5Dread_string") < 0)
|
||||
goto done;
|
||||
|
||||
if (!(str_len = H5Tget_size((hid_t)mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1074,6 +1096,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1string(JNIEnv *env, jclass clss, jlong dataset_id,
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dwrite_string: write buffer length <= 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per selected point. */
|
||||
if (h5d_validate_slot_buf(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id, n,
|
||||
"H5Dwrite_string") < 0)
|
||||
goto done;
|
||||
|
||||
if (!(str_len = H5Tget_size((hid_t)mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1132,6 +1159,7 @@ Java_hdf_hdf5lib_H5_H5DreadVL(JNIEnv *env, jclass clss, jlong dataset_id, jlong
|
||||
size_t typeSize;
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len;
|
||||
hssize_t npoints;
|
||||
htri_t vl_data_class;
|
||||
herr_t status = FAIL;
|
||||
htri_t is_variable = 0;
|
||||
@@ -1151,6 +1179,13 @@ Java_hdf_hdf5lib_H5_H5DreadVL(JNIEnv *env, jclass clss, jlong dataset_id, jlong
|
||||
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* The buffer must hold at least one slot per selected point; otherwise the
|
||||
* H5Dread below would overrun the raw read buffer. */
|
||||
if ((npoints = h5d_io_npoints(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id)) < 0)
|
||||
goto done;
|
||||
if ((hssize_t)vl_array_len < npoints)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5DreadVL: read buffer is smaller than the selection");
|
||||
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1163,7 +1198,7 @@ Java_hdf_hdf5lib_H5_H5DreadVL(JNIEnv *env, jclass clss, jlong dataset_id, jlong
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf);
|
||||
translate_rbuf(env, buf, mem_type_id, type_class, vl_array_len, readBuf, (size_t)vl_array_len * typeSize);
|
||||
|
||||
done:
|
||||
if (readBuf) {
|
||||
@@ -1192,6 +1227,7 @@ Java_hdf_hdf5lib_H5_H5DwriteVL(JNIEnv *env, jclass clss, jlong dataset_id, jlong
|
||||
size_t typeSize;
|
||||
H5T_class_t type_class;
|
||||
jsize vl_array_len; // Only used by vl_data_class types
|
||||
hssize_t npoints;
|
||||
htri_t vl_data_class;
|
||||
herr_t status = FAIL;
|
||||
htri_t is_variable = 0;
|
||||
@@ -1212,16 +1248,27 @@ Java_hdf_hdf5lib_H5_H5DwriteVL(JNIEnv *env, jclass clss, jlong dataset_id, jlong
|
||||
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Verify the buffer holds at least one element per selected point. */
|
||||
if ((npoints = h5d_io_npoints(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id)) < 0)
|
||||
goto done;
|
||||
if ((hssize_t)vl_array_len < npoints)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5DwriteVL: write buffer is smaller than the selection");
|
||||
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
if (NULL == (writeBuf = calloc((size_t)vl_array_len, typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5DwriteVL: failed to allocate raw VL write buffer");
|
||||
|
||||
if ((type_class = H5Tget_class((hid_t)mem_type_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf);
|
||||
/* Verify the buffer structure matches mem_type_id before converting it. */
|
||||
if (h5validate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len) < 0)
|
||||
goto done;
|
||||
|
||||
if (NULL == (writeBuf = calloc((size_t)vl_array_len, typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5DwriteVL: failed to allocate raw VL write buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, buf, mem_type_id, type_class, vl_array_len, writeBuf,
|
||||
(size_t)vl_array_len * typeSize);
|
||||
|
||||
if ((status = H5Dwrite((hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id,
|
||||
(hid_t)xfer_plist_id, writeBuf)) < 0)
|
||||
@@ -1266,6 +1313,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5DreadVLStrings: read buffer is NULL");
|
||||
|
||||
/* The buffer must have one slot per selected point. */
|
||||
if (h5d_validate_slot_buf(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id,
|
||||
ENVPTR->GetArrayLength(ENVONLY, buf), "H5Dread_VLStrings") < 0)
|
||||
goto done;
|
||||
|
||||
if ((isStr = H5Tdetect_class((hid_t)mem_type_id, H5T_STRING)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1492,6 +1544,11 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_
|
||||
if (NULL == buf)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5DwriteVLStrings: write buffer is NULL");
|
||||
|
||||
/* The buffer must have one slot per selected point. */
|
||||
if (h5d_validate_slot_buf(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id,
|
||||
ENVPTR->GetArrayLength(ENVONLY, buf), "H5Dwrite_VLStrings") < 0)
|
||||
goto done;
|
||||
|
||||
if ((isStr = H5Tdetect_class((hid_t)mem_type_id, H5T_STRING)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
@@ -1739,6 +1796,11 @@ Java_hdf_hdf5lib_H5_H5Dread_1reg_1ref(JNIEnv *env, jclass clss, jlong dataset_id
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5Dread_reg_ref: buf length < 0");
|
||||
}
|
||||
|
||||
/* The buffer must have one slot per selected point. */
|
||||
if (h5d_validate_slot_buf(env, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)dataset_id, n,
|
||||
"H5Dread_reg_ref") < 0)
|
||||
goto done;
|
||||
|
||||
if (NULL == (ref_data = (H5R_ref_t *)calloc(1, (size_t)n * sizeof(H5R_ref_t))))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Dread_reg_ref: failed to allocate read buffer");
|
||||
|
||||
|
||||
+602
-139
@@ -71,9 +71,23 @@ static int render_bin_output_region_data_points(FILE *stream, hid_t region_sp
|
||||
hsize_t *ptdata);
|
||||
static int render_bin_output_region_points(FILE *stream, hid_t region_space, hid_t region_id,
|
||||
hid_t container);
|
||||
jobject translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, void *raw_buf);
|
||||
jobject translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, void *raw_buf,
|
||||
size_t buf_size);
|
||||
void translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_t type_class,
|
||||
void *raw_buf);
|
||||
void *raw_buf, size_t buf_size);
|
||||
static herr_t h5validate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_t type_class);
|
||||
|
||||
/*
|
||||
* Raises an error if reading/writing LEN bytes at offset OFF would
|
||||
* overrun a buffer of size BUFSZ. OFF and LEN are byte values,
|
||||
* BUFSZ is the number of valid bytes at the buffer base.
|
||||
* WHERE is a string literal naming the calling routine.
|
||||
* ENV is the JNI environment pointer used to raise the error. */
|
||||
#define CHECK_RAWBUF_BOUNDS(env, off, len, bufsz, where) \
|
||||
do { \
|
||||
if ((size_t)(len) > (size_t)(bufsz) || (size_t)(off) > (size_t)(bufsz) - (size_t)(len)) \
|
||||
H5_BAD_ARGUMENT_ERROR(env, where ": raw buffer access out of bounds"); \
|
||||
} while (0)
|
||||
|
||||
/* Strings for output */
|
||||
#define H5_TOOLS_GROUP "GROUP"
|
||||
@@ -4237,7 +4251,7 @@ done:
|
||||
} /* end Java_hdf_hdf5lib_H5_H5export_1attribute */
|
||||
|
||||
jobject
|
||||
translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, void *raw_buf)
|
||||
translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, void *raw_buf, size_t buf_size)
|
||||
{
|
||||
jobject jobj = NULL;
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
@@ -4252,6 +4266,7 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
/* retrieve the java.util.ArrayList interface class */
|
||||
jclass arrCList = ENVPTR->FindClass(ENVONLY, "java/util/ArrayList");
|
||||
jmethodID arrListMethod = ENVPTR->GetMethodID(ENVONLY, arrCList, "<init>", "(I)V");
|
||||
jmethodID arrAddMethod = ENVPTR->GetMethodID(ENVONLY, arrCList, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
/* Cache class types */
|
||||
/* jclass cBool = ENVPTR->FindClass(ENVONLY, "java/lang/Boolean"); */
|
||||
@@ -4276,6 +4291,10 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* The element occupies [0, typeSize) of raw_buf, verify it fits. */
|
||||
if (typeSize > buf_size)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_rbuf: raw buffer smaller than element");
|
||||
|
||||
switch (type_class) {
|
||||
case H5T_VLEN: {
|
||||
if (!(memb = H5Tget_super(mem_type_id)))
|
||||
@@ -4301,22 +4320,21 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)nelmts, vl_elem.p);
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)nelmts, vl_elem.p, (size_t)nelmts * vlSize);
|
||||
jobj = jList;
|
||||
break;
|
||||
} /* H5T_VLEN */
|
||||
case H5T_COMPOUND: {
|
||||
int nmembs = H5Tget_nmembers(mem_type_id);
|
||||
|
||||
/* The list we're going to return: */
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate list read buffer");
|
||||
|
||||
/* Convert each element to a compound object */
|
||||
for (i = 0; i < (size_t)nmembs; i++) {
|
||||
H5T_class_t memb_vlClass;
|
||||
size_t memb_vlSize;
|
||||
size_t memb_offset;
|
||||
jobject memb_jobj;
|
||||
|
||||
if ((memb = H5Tget_member_type(mem_type_id, (unsigned int)i)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
@@ -4326,7 +4344,14 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
if (!(memb_vlSize = H5Tget_size(memb)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
translate_atomic_rbuf(ENVONLY, memb, memb_vlClass, char_buf + i * typeSize + memb_offset);
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, memb_offset, memb_vlSize, buf_size, "translate_atomic_rbuf");
|
||||
memb_jobj =
|
||||
translate_atomic_rbuf(ENVONLY, memb, memb_vlClass, char_buf + memb_offset, memb_vlSize);
|
||||
if (memb_jobj) {
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, jList, arrAddMethod, memb_jobj);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, memb_jobj);
|
||||
}
|
||||
H5Tclose(memb);
|
||||
}
|
||||
jobj = jList;
|
||||
@@ -4358,7 +4383,7 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)typeCount, objBuf);
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)typeCount, objBuf, typeSize);
|
||||
jobj = jList;
|
||||
|
||||
if (objBuf)
|
||||
@@ -4368,7 +4393,6 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
} /* H5T_ARRAY */
|
||||
case H5T_ENUM:
|
||||
case H5T_BITFIELD:
|
||||
case H5T_OPAQUE:
|
||||
case H5T_INTEGER: {
|
||||
/* Convert each element */
|
||||
switch (typeSize) {
|
||||
@@ -4441,7 +4465,11 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
}
|
||||
break;
|
||||
} /* H5T_FLOAT */
|
||||
case H5T_OPAQUE:
|
||||
case H5T_REFERENCE: {
|
||||
/* Opaque elements are arbitrary-sized byte blobs with no matching
|
||||
* Java scalar type, so they use the same byte[]-per-element model
|
||||
* as references. */
|
||||
/* Convert each element to a list */
|
||||
jboolean bb;
|
||||
jbyte *barray = NULL;
|
||||
@@ -4471,7 +4499,14 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
/* Convert each element */
|
||||
if (is_variable) {
|
||||
char **var_str_buf = (char **)raw_buf;
|
||||
if (NULL == (jobj = ENVPTR->NewStringUTF(ENVONLY, *var_str_buf))) {
|
||||
/* Passing NULL to NewStringUTF leads to a crash. A NULL pointer here
|
||||
* usually means H5Dread did not fill this slot (e.g., if
|
||||
* caller passed an over-sized buffer). If this happens, return null
|
||||
* rather than dereferencing. */
|
||||
if (*var_str_buf == NULL) {
|
||||
jobj = NULL;
|
||||
}
|
||||
else if (NULL == (jobj = ENVPTR->NewStringUTF(ENVONLY, *var_str_buf))) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: out of memory - unable to "
|
||||
"construct string from UTF characters");
|
||||
@@ -4512,7 +4547,7 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf);
|
||||
translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf, typeSize);
|
||||
jobj = jList;
|
||||
|
||||
if (objBuf)
|
||||
@@ -4534,7 +4569,8 @@ done:
|
||||
}
|
||||
|
||||
void
|
||||
translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_t type_class, void *raw_buf)
|
||||
translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_t type_class, void *raw_buf,
|
||||
size_t buf_size)
|
||||
{
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
H5T_class_t vlClass;
|
||||
@@ -4567,6 +4603,10 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* The element occupies [0, typeSize) of raw_buf, verify it fits. */
|
||||
if (typeSize > buf_size)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: raw buffer smaller than element");
|
||||
|
||||
switch (type_class) {
|
||||
case H5T_VLEN: {
|
||||
if (!(memb = H5Tget_super(mem_type_id)))
|
||||
@@ -4576,22 +4616,33 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
if (!(vlSize = H5Tget_size(memb)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Convert element to a vlen element */
|
||||
hvl_t vl_elem;
|
||||
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, in_obj);
|
||||
/* Convert ArrayList to plain array */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == in_obj)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: VL in_obj is NULL");
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: number of VL elements < 0");
|
||||
|
||||
/* Convert element to a vlen element */
|
||||
hvl_t vl_elem;
|
||||
vl_elem.len = (size_t)jnelmts;
|
||||
|
||||
if (NULL == (vl_elem.p = malloc((size_t)jnelmts * vlSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_wbuf: failed to allocate vlen ptr buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, (jobjectArray)in_obj, memb, vlClass, (jsize)jnelmts, vl_elem.p);
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, (jsize)jnelmts, vl_elem.p,
|
||||
(size_t)jnelmts * vlSize);
|
||||
|
||||
memcpy(char_buf, &vl_elem, sizeof(hvl_t));
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
} /* H5T_VLEN */
|
||||
case H5T_COMPOUND: {
|
||||
@@ -4601,8 +4652,13 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
if (NULL == in_obj)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: compound in_obj is NULL");
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts != nmembs)
|
||||
H5_BAD_ARGUMENT_ERROR(
|
||||
@@ -4623,11 +4679,14 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
jobject arr_obj = ENVPTR->GetObjectArrayElement(ENVONLY, array, (jsize)i);
|
||||
translate_atomic_wbuf(ENVONLY, arr_obj, memb, memb_vlClass,
|
||||
char_buf + i * typeSize + memb_offset);
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, memb_offset, memb_vlSize, buf_size, "translate_atomic_wbuf");
|
||||
translate_atomic_wbuf(ENVONLY, arr_obj, memb, memb_vlClass, char_buf + memb_offset,
|
||||
memb_vlSize);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, arr_obj);
|
||||
H5Tclose(memb);
|
||||
}
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
} /* H5T_COMPOUND */
|
||||
case H5T_ARRAY: {
|
||||
@@ -4644,8 +4703,13 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
if (NULL == in_obj)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: array in_obj is NULL");
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: number of array elements < 0");
|
||||
@@ -4653,14 +4717,15 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
if (NULL == (objBuf = malloc((size_t)jnelmts * vlSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_wbuf: failed to allocate buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, (jsize)jnelmts, objBuf);
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, (jsize)jnelmts, objBuf, (size_t)jnelmts * vlSize);
|
||||
|
||||
memcpy(char_buf, (char *)objBuf, vlSize * (size_t)jnelmts);
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
} /* H5T_ARRAY */
|
||||
case H5T_ENUM:
|
||||
case H5T_BITFIELD:
|
||||
case H5T_OPAQUE:
|
||||
case H5T_INTEGER: {
|
||||
/* Convert each element */
|
||||
switch (typeSize) {
|
||||
@@ -4709,7 +4774,10 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
}
|
||||
break;
|
||||
} /* H5T_FLOAT */
|
||||
case H5T_OPAQUE:
|
||||
case H5T_REFERENCE: {
|
||||
/* Opaque elements are arbitrary-sized byte blobs and use the same
|
||||
* byte[]-per-element model as references. */
|
||||
/* Convert each array element */
|
||||
jbyte *barray = (jbyte *)ENVPTR->GetByteArrayElements(ENVONLY, in_obj, 0);
|
||||
memcpy(char_buf, ((char *)barray), typeSize);
|
||||
@@ -4761,8 +4829,13 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
/* Convert each array element - invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
if (NULL == in_obj)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: complex in_obj is NULL");
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: number of array elements < 0");
|
||||
@@ -4770,13 +4843,15 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_
|
||||
if (NULL == (objBuf = malloc((size_t)jnelmts * base_size)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_wbuf: failed to allocate buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, array, memb, base_class, (jsize)jnelmts, objBuf);
|
||||
translate_wbuf(ENVONLY, array, memb, base_class, (jsize)jnelmts, objBuf,
|
||||
(size_t)jnelmts * base_size);
|
||||
|
||||
memcpy(char_buf, (char *)objBuf, base_size * (size_t)jnelmts);
|
||||
|
||||
if (objBuf)
|
||||
free(objBuf);
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
}
|
||||
case H5T_TIME:
|
||||
@@ -4792,15 +4867,37 @@ done:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Buffer data model (see also the "Buffer data model" section in H5.java).
|
||||
*
|
||||
* translate_rbuf()/translate_wbuf() convert between the packed ("raw") C buffer
|
||||
* that the HDF5 library reads into / writes from and the Java object tree that
|
||||
* the public API exposes. The expected Java representation per memory-datatype
|
||||
* class is:
|
||||
*
|
||||
* - integer/enum/bitfield, float: the boxed scalar type (Byte/Short/Integer/
|
||||
* Long for integers sized 1/2/4/8, Float/Double for floats).
|
||||
* - fixed- or variable-length string: a java.lang.String (null permitted on
|
||||
* write, where it is written as a zeroed element).
|
||||
* - reference, opaque: a Java byte[] holding one element's raw bytes. Opaque
|
||||
* elements are arbitrary-sized blobs with no matching Java scalar type, so
|
||||
* they follow the same model as references.
|
||||
* - compound, variable-length sequence, array, complex: a java.util.ArrayList.
|
||||
* A compound is an ArrayList of its members in declaration order; a VLEN/
|
||||
* array/complex is an ArrayList of its elements; scalar leaves are the boxed
|
||||
* types above. Nesting is handled by recursing through translate_atomic_*.
|
||||
*
|
||||
* On read the top-level container is the caller's Java Object[]; recursive calls
|
||||
* append to ArrayLists. Per-element slots are not pre-allocated by the caller.
|
||||
*/
|
||||
void
|
||||
translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t type_class, jsize count,
|
||||
void *raw_buf)
|
||||
void *raw_buf, size_t buf_size)
|
||||
{
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
int ret_buflen = -1;
|
||||
jboolean found_jList = JNI_TRUE;
|
||||
jobjectArray jList = NULL;
|
||||
jobject jobj = NULL;
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
jboolean retIsList = JNI_FALSE;
|
||||
jobjectArray jList = NULL;
|
||||
jobject jobj = NULL;
|
||||
H5T_class_t vlClass;
|
||||
size_t vlSize;
|
||||
size_t i, x;
|
||||
@@ -4816,9 +4913,12 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
ret_buflen = ENVPTR->GetArrayLength(ENVONLY, ret_buf);
|
||||
if (ret_buflen < 0)
|
||||
H5_JNI_FATAL_ERROR(ENVONLY, "ret_buflen: Array length cannot be negative");
|
||||
/* Top-level calls pass a Java Object[] array; recursive calls pass an
|
||||
* ArrayList. Detect which so the append-vs-set decision is unambiguous.
|
||||
*
|
||||
* Caller-side pre-allocation of per-element slots is not supported.
|
||||
* Any object already present in a Java array slot is overwritten. */
|
||||
retIsList = ENVPTR->IsInstanceOf(ENVONLY, ret_buf, arrCList);
|
||||
|
||||
switch (type_class) {
|
||||
case H5T_VLEN: {
|
||||
@@ -4829,68 +4929,41 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
if (!(vlSize = H5Tget_size(memb)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
/* Convert each element to a list */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
hvl_t vl_elem;
|
||||
|
||||
found_jList = JNI_TRUE;
|
||||
jList = NULL;
|
||||
|
||||
/* Get the number of sequence elements */
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * sizeof(hvl_t), sizeof(hvl_t), buf_size, "translate_rbuf");
|
||||
memcpy(&vl_elem, char_buf + i * sizeof(hvl_t), sizeof(hvl_t));
|
||||
jsize nelmts = (jsize)vl_elem.len;
|
||||
if (vl_elem.len != (size_t)nelmts)
|
||||
H5_JNI_FATAL_ERROR(ENVONLY, "translate_rbuf: overflow of number of VL elements");
|
||||
|
||||
if (nelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_rbuf: number of VL elements < 0");
|
||||
|
||||
/* The list we're going to return: */
|
||||
if (i < (size_t)ret_buflen) {
|
||||
jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)ret_buf, (jsize)i);
|
||||
}
|
||||
if (NULL == jList) {
|
||||
found_jList = JNI_FALSE;
|
||||
if (NULL ==
|
||||
(jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
|
||||
"translate_rbuf: failed to allocate list read buffer");
|
||||
}
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)nelmts, vl_elem.p);
|
||||
if (found_jList == JNI_FALSE) {
|
||||
jboolean addResult =
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, (jobject)jList);
|
||||
if (!addResult)
|
||||
H5_JNI_FATAL_ERROR(ENVONLY, "translate_rbuf: cannot add VL element");
|
||||
}
|
||||
else {
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)nelmts, vl_elem.p,
|
||||
(size_t)nelmts * vlSize);
|
||||
|
||||
/* ArrayList (recursive call): append. Java array: install at slot i. */
|
||||
if (retIsList)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, (jobject)jList);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, (jobject)jList);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
}
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jList);
|
||||
}
|
||||
break;
|
||||
} /* H5T_VLEN */
|
||||
case H5T_COMPOUND: {
|
||||
/* Convert each compound element to a list */
|
||||
/* Convert each compound element to a fresh ArrayList of its members. */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
found_jList = JNI_TRUE;
|
||||
jList = NULL;
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate list read buffer");
|
||||
|
||||
/* The list we're going to return: */
|
||||
if (i < (size_t)ret_buflen) {
|
||||
jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)ret_buf, (jsize)i);
|
||||
}
|
||||
if (NULL == jList) {
|
||||
found_jList = JNI_FALSE;
|
||||
if (NULL ==
|
||||
(jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
|
||||
"translate_rbuf: failed to allocate list read buffer");
|
||||
}
|
||||
int nmembs = H5Tget_nmembers(mem_type_id);
|
||||
/* Convert each element to a list */
|
||||
/* Append each member's value to this row's ArrayList */
|
||||
for (x = 0; x < (size_t)nmembs; x++) {
|
||||
H5T_class_t memb_vlClass;
|
||||
size_t memb_vlSize;
|
||||
@@ -4905,20 +4978,19 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
if (!(memb_vlSize = H5Tget_size(memb)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize + memb_offset, memb_vlSize, buf_size,
|
||||
"translate_rbuf");
|
||||
jobj = translate_atomic_rbuf(ENVONLY, memb, memb_vlClass,
|
||||
char_buf + i * typeSize + memb_offset);
|
||||
char_buf + i * typeSize + memb_offset, memb_vlSize);
|
||||
if (jobj) {
|
||||
if (found_jList == JNI_FALSE)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, jList, arrAddMethod, (jobject)jobj);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, jList, (jsize)i, (jobject)jobj);
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, jList, arrAddMethod, (jobject)jobj);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jobj);
|
||||
}
|
||||
|
||||
H5Tclose(memb);
|
||||
}
|
||||
if (ret_buflen == 0)
|
||||
if (retIsList)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
|
||||
@@ -4945,29 +5017,18 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
if (NULL == (objBuf = malloc(typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate buffer");
|
||||
|
||||
/* Convert each element to a list */
|
||||
/* Convert each element to a fresh list */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
found_jList = JNI_TRUE;
|
||||
jList = NULL;
|
||||
|
||||
/* Get the object element */
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize, typeSize, buf_size, "translate_rbuf");
|
||||
memcpy((char *)objBuf, char_buf + i * typeSize, typeSize);
|
||||
|
||||
/* The list we're going to return: */
|
||||
if (i < (size_t)ret_buflen) {
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)ret_buf, (jsize)i)))
|
||||
found_jList = JNI_FALSE;
|
||||
}
|
||||
if (NULL == jList) {
|
||||
if (NULL ==
|
||||
(jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
|
||||
"translate_rbuf: failed to allocate list read buffer");
|
||||
}
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)typeCount, objBuf);
|
||||
if (found_jList == JNI_FALSE)
|
||||
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)typeCount, objBuf, typeSize);
|
||||
if (retIsList)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
|
||||
@@ -4989,9 +5050,11 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
case H5T_STRING: {
|
||||
/* Convert each element to a list */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
jobj = translate_atomic_rbuf(ENVONLY, mem_type_id, type_class, char_buf + i * typeSize);
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize, typeSize, buf_size, "translate_rbuf");
|
||||
jobj = translate_atomic_rbuf(ENVONLY, mem_type_id, type_class, char_buf + i * typeSize,
|
||||
typeSize);
|
||||
if (jobj) {
|
||||
if (ret_buflen == 0)
|
||||
if (retIsList)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, (jobject)jobj);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, (jobject)jobj);
|
||||
@@ -5020,29 +5083,18 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t
|
||||
if (NULL == (objBuf = malloc(typeSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer");
|
||||
|
||||
/* Convert each element to a list of 2 floating-point elements */
|
||||
/* Convert each element to a fresh list of 2 floating-point elements */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
found_jList = JNI_TRUE;
|
||||
jList = NULL;
|
||||
|
||||
/* Get the object element */
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize, typeSize, buf_size, "translate_rbuf");
|
||||
memcpy((char *)objBuf, char_buf + i * typeSize, typeSize);
|
||||
|
||||
/* The list we're going to return: */
|
||||
if (i < (size_t)ret_buflen) {
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)ret_buf, (jsize)i)))
|
||||
found_jList = JNI_FALSE;
|
||||
}
|
||||
if (NULL == jList) {
|
||||
if (NULL ==
|
||||
(jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
|
||||
"translate_rbuf: failed to allocate list read buffer");
|
||||
}
|
||||
if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate list read buffer");
|
||||
|
||||
translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf);
|
||||
if (found_jList == JNI_FALSE)
|
||||
translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf, typeSize);
|
||||
if (retIsList)
|
||||
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
|
||||
else
|
||||
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
|
||||
@@ -5068,9 +5120,16 @@ done:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write counterpart to translate_rbuf(); see the "Buffer data model" comment on
|
||||
* translate_rbuf() (and in H5.java) for the Java-to-C representation of each
|
||||
* datatype class. On write the Java buffer is validated up front by
|
||||
* h5validate_wbuf() so a mismatch raises IllegalArgumentException at the API
|
||||
* boundary instead of corrupting the packed buffer here.
|
||||
*/
|
||||
void
|
||||
translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t type_class, jsize count,
|
||||
void *raw_buf)
|
||||
void *raw_buf, size_t buf_size)
|
||||
{
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
jobjectArray jList = NULL;
|
||||
@@ -5103,14 +5162,23 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
hvl_t vl_elem;
|
||||
|
||||
if (NULL == (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i)))
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i))) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: in_buf element is NULL");
|
||||
}
|
||||
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, jList, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: VLEN slot is not a java.util.ArrayList");
|
||||
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: number of VL elements < 0");
|
||||
@@ -5120,10 +5188,13 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
if (NULL == (vl_elem.p = malloc((size_t)jnelmts * vlSize)))
|
||||
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_wbuf: failed to allocate vlen ptr buffer");
|
||||
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, (jsize)jnelmts, vl_elem.p);
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, (jsize)jnelmts, vl_elem.p,
|
||||
(size_t)jnelmts * vlSize);
|
||||
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * sizeof(hvl_t), sizeof(hvl_t), buf_size, "translate_wbuf");
|
||||
memcpy(char_buf + i * sizeof(hvl_t), &vl_elem, sizeof(hvl_t));
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jList);
|
||||
} /* end for (i = 0; i < count; i++) */
|
||||
break;
|
||||
@@ -5131,16 +5202,26 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
case H5T_COMPOUND: {
|
||||
/* Convert each list to a compound element */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
if (NULL == (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i)))
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i))) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: in_buf element is NULL");
|
||||
}
|
||||
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, jList, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"translate_wbuf: COMPOUND slot is not a java.util.ArrayList");
|
||||
|
||||
int nmembs = H5Tget_nmembers(mem_type_id);
|
||||
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts != nmembs)
|
||||
H5_BAD_ARGUMENT_ERROR(
|
||||
@@ -5162,12 +5243,15 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
jobject arr_obj = ENVPTR->GetObjectArrayElement(ENVONLY, array, (jsize)x);
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize + memb_offset, memb_vlSize, buf_size,
|
||||
"translate_wbuf");
|
||||
translate_atomic_wbuf(ENVONLY, arr_obj, memb, memb_vlClass,
|
||||
char_buf + i * typeSize + memb_offset);
|
||||
char_buf + i * typeSize + memb_offset, memb_vlSize);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, arr_obj);
|
||||
H5Tclose(memb);
|
||||
}
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jList);
|
||||
} /* end for (i = 0; i < count; i++) */
|
||||
break;
|
||||
@@ -5182,21 +5266,33 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
|
||||
/* Convert each list to an array element */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
if (NULL == (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i)))
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i))) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: in_buf element is NULL");
|
||||
}
|
||||
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, jList, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: ARRAY slot is not a java.util.ArrayList");
|
||||
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: number of array elements < 0");
|
||||
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * vlSize * (size_t)jnelmts, vlSize * (size_t)jnelmts, buf_size,
|
||||
"translate_wbuf");
|
||||
translate_wbuf(ENVONLY, array, memb, vlClass, jnelmts,
|
||||
char_buf + i * vlSize * (size_t)jnelmts);
|
||||
char_buf + i * vlSize * (size_t)jnelmts, vlSize * (size_t)jnelmts);
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jList);
|
||||
} /* end for (i = 0; i < count; i++) */
|
||||
break;
|
||||
@@ -5212,7 +5308,9 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
if (NULL == (jobj = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i)))
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
translate_atomic_wbuf(ENVONLY, jobj, mem_type_id, type_class, char_buf + i * typeSize);
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * typeSize, typeSize, buf_size, "translate_wbuf");
|
||||
translate_atomic_wbuf(ENVONLY, jobj, mem_type_id, type_class, char_buf + i * typeSize,
|
||||
typeSize);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jobj);
|
||||
}
|
||||
break;
|
||||
@@ -5230,21 +5328,34 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t
|
||||
|
||||
/* Convert each list to an array element */
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
if (NULL == (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i)))
|
||||
if (NULL ==
|
||||
(jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i))) {
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: in_buf element is NULL");
|
||||
}
|
||||
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, jList, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"translate_wbuf: COMPLEX slot is not a java.util.ArrayList");
|
||||
|
||||
/* invoke the toArray method */
|
||||
if (mToArray == NULL)
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_NULL_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: ArrayList.toArray returned NULL");
|
||||
jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (jnelmts < 0)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: number of array elements < 0");
|
||||
|
||||
CHECK_RAWBUF_BOUNDS(ENVONLY, i * base_size * (size_t)jnelmts, base_size * (size_t)jnelmts,
|
||||
buf_size, "translate_wbuf");
|
||||
translate_wbuf(ENVONLY, array, memb, base_class, jnelmts,
|
||||
char_buf + i * base_size * (size_t)jnelmts);
|
||||
char_buf + i * base_size * (size_t)jnelmts, base_size * (size_t)jnelmts);
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, jList);
|
||||
} /* end for (i = 0; i < count; i++) */
|
||||
|
||||
@@ -5263,6 +5374,358 @@ done:
|
||||
return;
|
||||
}
|
||||
|
||||
hssize_t
|
||||
h5d_io_npoints(JNIEnv *env, hid_t mem_space_id, hid_t file_space_id, hid_t dataset_id)
|
||||
{
|
||||
hssize_t ret_value = -1;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
|
||||
if (mem_space_id != H5S_ALL) {
|
||||
if ((ret_value = H5Sget_select_npoints(mem_space_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
}
|
||||
else if (file_space_id != H5S_ALL) {
|
||||
if ((ret_value = H5Sget_select_npoints(file_space_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
}
|
||||
else {
|
||||
if ((sid = H5Dget_space(dataset_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if ((ret_value = H5Sget_simple_extent_npoints(sid)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
}
|
||||
|
||||
done:
|
||||
if (sid >= 0)
|
||||
H5Sclose(sid);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
hssize_t
|
||||
h5a_io_npoints(JNIEnv *env, hid_t attr_id)
|
||||
{
|
||||
hssize_t ret_value = -1;
|
||||
hid_t sid = H5I_INVALID_HID;
|
||||
|
||||
if ((sid = H5Aget_space(attr_id)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if ((ret_value = H5Sget_simple_extent_npoints(sid)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
done:
|
||||
if (sid >= 0)
|
||||
H5Sclose(sid);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a single Java object matches the structure expected when writing
|
||||
* one element of type mem_type_id. Mirrors the per-element handling of
|
||||
* translate_atomic_wbuf/translate_wbuf, but only inspects types -- it converts
|
||||
* nothing and writes nothing. Composite classes recurse through h5validate_wbuf.
|
||||
*/
|
||||
static herr_t
|
||||
h5validate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_t type_class)
|
||||
{
|
||||
herr_t ret_value = FAIL;
|
||||
hid_t memb = H5I_INVALID_HID;
|
||||
H5T_class_t vlClass;
|
||||
size_t typeSize;
|
||||
size_t i;
|
||||
|
||||
jclass arrCList = ENVPTR->FindClass(ENVONLY, "java/util/ArrayList");
|
||||
jmethodID mToArray = ENVPTR->GetMethodID(ENVONLY, arrCList, "toArray", "()[Ljava/lang/Object;");
|
||||
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
switch (type_class) {
|
||||
case H5T_VLEN:
|
||||
case H5T_ARRAY:
|
||||
case H5T_COMPLEX: {
|
||||
jobjectArray array;
|
||||
jsize nelmts;
|
||||
|
||||
if (NULL == in_obj)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: expected a java.util.ArrayList element, got null");
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, in_obj, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5validate_wbuf: expected a java.util.ArrayList element");
|
||||
|
||||
if (!(memb = H5Tget_super(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if ((vlClass = H5Tget_class(memb)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5validate_wbuf: ArrayList.toArray returned NULL");
|
||||
nelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
|
||||
if (type_class == H5T_COMPLEX && nelmts != 2)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: complex element must contain exactly 2 values");
|
||||
if (type_class == H5T_ARRAY) {
|
||||
size_t baseSize;
|
||||
if (!(baseSize = H5Tget_size(memb)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if ((size_t)nelmts != typeSize / baseSize)
|
||||
H5_BAD_ARGUMENT_ERROR(
|
||||
ENVONLY, "h5validate_wbuf: array element count does not match array datatype");
|
||||
}
|
||||
|
||||
if (h5validate_wbuf(ENVONLY, array, memb, vlClass, nelmts) < 0)
|
||||
goto done;
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
}
|
||||
case H5T_COMPOUND: {
|
||||
jobjectArray array;
|
||||
jsize nelmts;
|
||||
int nmembs = H5Tget_nmembers(mem_type_id);
|
||||
|
||||
if (nmembs < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if (NULL == in_obj)
|
||||
H5_BAD_ARGUMENT_ERROR(
|
||||
ENVONLY, "h5validate_wbuf: expected a java.util.ArrayList compound element, got null");
|
||||
if (!ENVPTR->IsInstanceOf(ENVONLY, in_obj, arrCList))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: expected a java.util.ArrayList compound element");
|
||||
|
||||
array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (NULL == array)
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5validate_wbuf: ArrayList.toArray returned NULL");
|
||||
nelmts = ENVPTR->GetArrayLength(ENVONLY, array);
|
||||
if (nelmts != nmembs)
|
||||
H5_BAD_ARGUMENT_ERROR(
|
||||
ENVONLY, "h5validate_wbuf: compound element member count does not match datatype");
|
||||
|
||||
for (i = 0; i < (size_t)nmembs; i++) {
|
||||
H5T_class_t memb_class;
|
||||
jobject memb_obj;
|
||||
|
||||
if ((memb = H5Tget_member_type(mem_type_id, (unsigned)i)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
if ((memb_class = H5Tget_class(memb)) < 0)
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
memb_obj = ENVPTR->GetObjectArrayElement(ENVONLY, array, (jsize)i);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
if (h5validate_atomic_wbuf(ENVONLY, memb_obj, memb, memb_class) < 0)
|
||||
goto done;
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, memb_obj);
|
||||
H5Tclose(memb);
|
||||
memb = H5I_INVALID_HID;
|
||||
}
|
||||
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, array);
|
||||
break;
|
||||
}
|
||||
case H5T_INTEGER:
|
||||
case H5T_ENUM:
|
||||
case H5T_BITFIELD: {
|
||||
const char *clsname;
|
||||
switch (typeSize) {
|
||||
case 1:
|
||||
clsname = "java/lang/Byte";
|
||||
break;
|
||||
case 2:
|
||||
clsname = "java/lang/Short";
|
||||
break;
|
||||
case 4:
|
||||
clsname = "java/lang/Integer";
|
||||
break;
|
||||
case 8:
|
||||
clsname = "java/lang/Long";
|
||||
break;
|
||||
default:
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: no matching boxed type for integer element size");
|
||||
}
|
||||
if (NULL == in_obj || !ENVPTR->IsInstanceOf(ENVONLY, in_obj, ENVPTR->FindClass(ENVONLY, clsname)))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: integer element is not the expected boxed type");
|
||||
break;
|
||||
}
|
||||
case H5T_FLOAT: {
|
||||
const char *clsname;
|
||||
switch (typeSize) {
|
||||
case 4:
|
||||
clsname = "java/lang/Float";
|
||||
break;
|
||||
case 8:
|
||||
clsname = "java/lang/Double";
|
||||
break;
|
||||
default:
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: no matching boxed type for float element size");
|
||||
}
|
||||
if (NULL == in_obj || !ENVPTR->IsInstanceOf(ENVONLY, in_obj, ENVPTR->FindClass(ENVONLY, clsname)))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY,
|
||||
"h5validate_wbuf: float element is not the expected boxed type");
|
||||
break;
|
||||
}
|
||||
case H5T_STRING: {
|
||||
/* A null element is permitted; translate_atomic_wbuf writes a zeroed value. */
|
||||
if (NULL != in_obj &&
|
||||
!ENVPTR->IsInstanceOf(ENVONLY, in_obj, ENVPTR->FindClass(ENVONLY, "java/lang/String")))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5validate_wbuf: string element is not a java.lang.String");
|
||||
break;
|
||||
}
|
||||
case H5T_OPAQUE:
|
||||
case H5T_REFERENCE: {
|
||||
/* translate_atomic_wbuf reads a Java byte[] for references and for
|
||||
* opaque elements (opaque is an arbitrary-sized byte blob). */
|
||||
if (NULL == in_obj || !ENVPTR->IsInstanceOf(ENVONLY, in_obj, ENVPTR->FindClass(ENVONLY, "[B")))
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5validate_wbuf: reference/opaque element is not a byte[]");
|
||||
break;
|
||||
}
|
||||
case H5T_TIME:
|
||||
case H5T_NO_CLASS:
|
||||
case H5T_NCLASSES:
|
||||
default:
|
||||
H5_UNIMPLEMENTED(ENVONLY, "h5validate_wbuf: invalid class type");
|
||||
} /* switch(type_class) */
|
||||
|
||||
ret_value = SUCCEED;
|
||||
|
||||
done:
|
||||
if (memb >= 0)
|
||||
H5Tclose(memb);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
herr_t
|
||||
h5validate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t type_class, jsize count)
|
||||
{
|
||||
herr_t ret_value = FAIL;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (size_t)count; i++) {
|
||||
jobject elem = ENVPTR->GetObjectArrayElement(ENVONLY, in_buf, (jsize)i);
|
||||
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
|
||||
|
||||
if (h5validate_atomic_wbuf(ENVONLY, elem, mem_type_id, type_class) < 0) {
|
||||
if (elem)
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, elem);
|
||||
goto done;
|
||||
}
|
||||
if (elem)
|
||||
ENVPTR->DeleteLocalRef(ENVONLY, elem);
|
||||
}
|
||||
|
||||
ret_value = SUCCEED;
|
||||
|
||||
done:
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Capacity check for a packed ("raw") read/write buffer: a Java array of
|
||||
* `buf_len` elements of `elem_size` bytes must be large enough to hold
|
||||
* `npoints` values of type `mem_type_id`. This is the invariant that keeps
|
||||
* H5Dread/H5Dwrite from running past the pinned Java array when the buffer kind
|
||||
* or length does not match the datatype/selection. Raises a descriptive
|
||||
* IllegalArgumentException and returns a negative value on mismatch.
|
||||
*/
|
||||
static herr_t
|
||||
h5validate_raw_capacity(JNIEnv *env, hid_t mem_type_id, hssize_t npoints, jsize buf_len, size_t elem_size,
|
||||
const char *where)
|
||||
{
|
||||
herr_t ret_value = FAIL;
|
||||
size_t typeSize;
|
||||
size_t have, need;
|
||||
char msg[192];
|
||||
|
||||
if (buf_len < 0) {
|
||||
snprintf(msg, sizeof(msg), "%s: buffer length < 0", where);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, msg);
|
||||
}
|
||||
if (!(typeSize = H5Tget_size(mem_type_id)))
|
||||
H5_LIBRARY_ERROR(ENVONLY);
|
||||
|
||||
have = (size_t)buf_len * elem_size;
|
||||
need = (size_t)npoints * typeSize;
|
||||
if (have < need) {
|
||||
snprintf(msg, sizeof(msg), "%s: buffer holds %zu bytes but the selection requires %zu bytes", where,
|
||||
have, need);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, msg);
|
||||
}
|
||||
|
||||
ret_value = SUCCEED;
|
||||
done:
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slot-count check for a String[]-style read/write buffer (fixed/variable
|
||||
* strings and references): the array must have at least one slot per selected
|
||||
* point. The library fills/consumes one Java String (or byte[]) per element.
|
||||
*/
|
||||
static herr_t
|
||||
h5validate_slot_count(JNIEnv *env, hssize_t npoints, jsize buf_len, const char *where)
|
||||
{
|
||||
herr_t ret_value = FAIL;
|
||||
char msg[160];
|
||||
|
||||
if (buf_len < 0 || (hssize_t)buf_len < npoints) {
|
||||
snprintf(msg, sizeof(msg), "%s: buffer has %d slots but the selection requires %lld", where,
|
||||
(int)buf_len, (long long)npoints);
|
||||
H5_BAD_ARGUMENT_ERROR(ENVONLY, msg);
|
||||
}
|
||||
|
||||
ret_value = SUCCEED;
|
||||
done:
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
herr_t
|
||||
h5d_validate_raw_buf(JNIEnv *env, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
|
||||
hid_t dataset_id, jsize buf_len, size_t elem_size, const char *where)
|
||||
{
|
||||
hssize_t npoints;
|
||||
|
||||
if ((npoints = h5d_io_npoints(env, mem_space_id, file_space_id, dataset_id)) < 0)
|
||||
return FAIL;
|
||||
return h5validate_raw_capacity(env, mem_type_id, npoints, buf_len, elem_size, where);
|
||||
}
|
||||
|
||||
herr_t
|
||||
h5a_validate_raw_buf(JNIEnv *env, hid_t mem_type_id, hid_t attr_id, jsize buf_len, size_t elem_size,
|
||||
const char *where)
|
||||
{
|
||||
hssize_t npoints;
|
||||
|
||||
if ((npoints = h5a_io_npoints(env, attr_id)) < 0)
|
||||
return FAIL;
|
||||
return h5validate_raw_capacity(env, mem_type_id, npoints, buf_len, elem_size, where);
|
||||
}
|
||||
|
||||
herr_t
|
||||
h5d_validate_slot_buf(JNIEnv *env, hid_t mem_space_id, hid_t file_space_id, hid_t dataset_id, jsize buf_len,
|
||||
const char *where)
|
||||
{
|
||||
hssize_t npoints;
|
||||
|
||||
if ((npoints = h5d_io_npoints(env, mem_space_id, file_space_id, dataset_id)) < 0)
|
||||
return FAIL;
|
||||
return h5validate_slot_count(env, npoints, buf_len, where);
|
||||
}
|
||||
|
||||
herr_t
|
||||
h5a_validate_slot_buf(JNIEnv *env, hid_t attr_id, jsize buf_len, const char *where)
|
||||
{
|
||||
hssize_t npoints;
|
||||
|
||||
if ((npoints = h5a_io_npoints(env, attr_id)) < 0)
|
||||
return FAIL;
|
||||
return h5validate_slot_count(env, npoints, buf_len, where);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -46,9 +46,42 @@ extern int h5str_dump_simple_mem(JNIEnv *env, FILE *stream, hid_t attr, int b
|
||||
extern htri_t H5Tdetect_variable_str(hid_t tid);
|
||||
|
||||
extern void translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t type_class,
|
||||
jsize count, void *raw_buf);
|
||||
jsize count, void *raw_buf, size_t buf_size);
|
||||
extern void translate_wbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t type_class,
|
||||
jsize count, void *raw_buf);
|
||||
jsize count, void *raw_buf, size_t buf_size);
|
||||
|
||||
/*
|
||||
* API-level buffer-contract verification helpers. These let the JNI entry
|
||||
* points reject a Java buffer whose structure does not match the documented
|
||||
* data-model for mem_type_id BEFORE any conversion or native I/O is attempted,
|
||||
* turning crashes/corruption into clean HDF5LibraryExceptions.
|
||||
*/
|
||||
|
||||
/* Number of elements selected for a dataset read/write (mem space, else file
|
||||
* space, else the dataset extent for H5S_ALL), or -1 on error. */
|
||||
extern hssize_t h5d_io_npoints(JNIEnv *env, hid_t mem_space_id, hid_t file_space_id, hid_t dataset_id);
|
||||
/* Number of elements in an attribute's dataspace, or -1 on error. */
|
||||
extern hssize_t h5a_io_npoints(JNIEnv *env, hid_t attr_id);
|
||||
|
||||
/* Recursively verify that a write buffer (top-level Java Object[] of `count`
|
||||
* elements) matches the nested ArrayList/boxed structure expected for
|
||||
* mem_type_id. Raises a descriptive H5_BAD_ARGUMENT_ERROR and returns a
|
||||
* negative value on the first mismatch; returns 0 if the structure is valid. */
|
||||
extern herr_t h5validate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t type_class,
|
||||
jsize count);
|
||||
|
||||
/* Capacity check for a packed (primitive-array or byte[]) dataset/attribute
|
||||
* buffer: `buf_len` elements of `elem_size` bytes must cover the selection of
|
||||
* mem_type_id. Raises IllegalArgumentException and returns negative on failure. */
|
||||
extern herr_t h5d_validate_raw_buf(JNIEnv *env, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
|
||||
hid_t dataset_id, jsize buf_len, size_t elem_size, const char *where);
|
||||
extern herr_t h5a_validate_raw_buf(JNIEnv *env, hid_t mem_type_id, hid_t attr_id, jsize buf_len,
|
||||
size_t elem_size, const char *where);
|
||||
/* Slot-count check for a String[]-style buffer (fixed/variable strings, refs):
|
||||
* the array must have at least one slot per selected point. */
|
||||
extern herr_t h5d_validate_slot_buf(JNIEnv *env, hid_t mem_space_id, hid_t file_space_id, hid_t dataset_id,
|
||||
jsize buf_len, const char *where);
|
||||
extern herr_t h5a_validate_slot_buf(JNIEnv *env, hid_t attr_id, jsize buf_len, const char *where);
|
||||
|
||||
/*
|
||||
* Symbols used to format the output of h5str_sprintf and
|
||||
|
||||
@@ -460,7 +460,7 @@ public class TestH5Arw {
|
||||
@Test
|
||||
public void testH5Aread_128bit_floats()
|
||||
{
|
||||
byte[][][] attr_data = new byte[DIM_X][DIM128_Y][8];
|
||||
byte[][][] attr_data = new byte[DIM_X][DIM128_Y][16];
|
||||
|
||||
try {
|
||||
openH5file(H5_FLTS_FILE, DATASETF128);
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
package test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -434,7 +436,7 @@ public class TestH5D {
|
||||
try {
|
||||
if (H5did >= 0)
|
||||
H5.H5Dwrite(H5did, HDF5Constants.H5T_NATIVE_INT, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, dset_data[0]);
|
||||
HDF5Constants.H5P_DEFAULT, dset_data);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -1755,6 +1757,166 @@ public class TestH5D {
|
||||
arr_str_data[3].get(0).equals(arr_readbuf[3].get(0)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify H5DreadVL safe throws a Java exception
|
||||
* when called with a malformed buffer shape for an ARRAY-of-varstr dataset.
|
||||
*/
|
||||
@Test
|
||||
public void testH5DArray_string_buffer_flat_StringArray() throws Throwable
|
||||
{
|
||||
String dset_str_name = "ArrayStringdata_flat";
|
||||
long dset_str_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dtype_str_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long varstr_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dspace_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long[] strdims = {3};
|
||||
long[] dims = {2};
|
||||
long lsize = 1;
|
||||
|
||||
String[] row0 = {"a", "bb", "ccc"};
|
||||
String[] row1 = {"dd", "ee", "fff"};
|
||||
|
||||
ArrayList[] arr_str_data = new ArrayList[2];
|
||||
arr_str_data[0] = new ArrayList<String>(Arrays.asList(row0));
|
||||
arr_str_data[1] = new ArrayList<String>(Arrays.asList(row1));
|
||||
|
||||
try {
|
||||
varstr_id = H5.H5Tcopy(HDF5Constants.H5T_C_S1);
|
||||
H5.H5Tset_size(varstr_id, HDF5Constants.H5T_VARIABLE);
|
||||
dtype_str_id = H5.H5Tarray_create(varstr_id, 1, strdims);
|
||||
|
||||
dspace_id = H5.H5Screate_simple(1, dims, null);
|
||||
dset_str_id =
|
||||
H5.H5Dcreate(H5fid, dset_str_name, dtype_str_id, dspace_id, HDF5Constants.H5P_DEFAULT,
|
||||
HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT);
|
||||
H5.H5DwriteVL(dset_str_id, dtype_str_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, arr_str_data);
|
||||
H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
|
||||
|
||||
for (int j = 0; j < dims.length; j++)
|
||||
lsize *= dims[j];
|
||||
|
||||
// Malformed buffer: a flat String[dims*array_dim], not
|
||||
// ArrayList[dims] of array_dim Strings.
|
||||
int flatLen = (int)lsize * (int)strdims[0];
|
||||
String[] badBuf = new String[flatLen];
|
||||
for (int j = 0; j < flatLen; j++)
|
||||
badBuf[j] = "";
|
||||
|
||||
// The JNI must not segfault here regardless of what badBuf looks
|
||||
// like. Either it correctly populates the slots or it throws.
|
||||
try {
|
||||
H5.H5DreadVL(dset_str_id, dtype_str_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, badBuf);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Accepted outcome: graceful Java-level error.
|
||||
return;
|
||||
}
|
||||
|
||||
assertNotNull("badBuf[0] should not be null after H5DreadVL", badBuf[0]);
|
||||
}
|
||||
finally {
|
||||
if (dset_str_id > 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_str_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dspace_id > 0)
|
||||
try {
|
||||
H5.H5Sclose(dspace_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dtype_str_id > 0)
|
||||
try {
|
||||
H5.H5Tclose(dtype_str_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (varstr_id > 0)
|
||||
try {
|
||||
H5.H5Tclose(varstr_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify H5DwriteVL safely throws a Java exception
|
||||
* when called with a malformed buffer shape for an ARRAY-of-varstr dataset.
|
||||
*/
|
||||
@Test
|
||||
public void testH5DArray_string_buffer_flat_StringArray_write() throws Throwable
|
||||
{
|
||||
String dset_str_name = "ArrayStringdata_flat_write";
|
||||
long dset_str_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dtype_str_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long varstr_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dspace_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long[] strdims = {3};
|
||||
long[] dims = {2};
|
||||
|
||||
try {
|
||||
varstr_id = H5.H5Tcopy(HDF5Constants.H5T_C_S1);
|
||||
H5.H5Tset_size(varstr_id, HDF5Constants.H5T_VARIABLE);
|
||||
dtype_str_id = H5.H5Tarray_create(varstr_id, 1, strdims);
|
||||
|
||||
dspace_id = H5.H5Screate_simple(1, dims, null);
|
||||
dset_str_id =
|
||||
H5.H5Dcreate(H5fid, dset_str_name, dtype_str_id, dspace_id, HDF5Constants.H5P_DEFAULT,
|
||||
HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT);
|
||||
|
||||
// Malformed buffer: a flat String[dims*array_dim], not
|
||||
// ArrayList[dims] of array_dim Strings.
|
||||
int flatLen = (int)dims[0] * (int)strdims[0];
|
||||
String[] flatBuf = new String[flatLen];
|
||||
for (int j = 0; j < flatLen; j++)
|
||||
flatBuf[j] = "s" + j;
|
||||
|
||||
try {
|
||||
H5.H5DwriteVL(dset_str_id, dtype_str_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, flatBuf);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Accepted outcome: graceful Java-level error.
|
||||
return;
|
||||
}
|
||||
|
||||
// If we reach here, no exception was thrown. Worst case is the JVM
|
||||
// segfaults before this line. If it accepted the write silently,
|
||||
// that itself indicates the JNI doesn't validate the buffer shape.
|
||||
}
|
||||
finally {
|
||||
if (dset_str_id > 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_str_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dspace_id > 0)
|
||||
try {
|
||||
H5.H5Sclose(dspace_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dtype_str_id > 0)
|
||||
try {
|
||||
H5.H5Tclose(dtype_str_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (varstr_id > 0)
|
||||
try {
|
||||
H5.H5Tclose(varstr_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testH5DArrayenum_rw()
|
||||
{
|
||||
@@ -1947,4 +2109,689 @@ public class TestH5D {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a 1-D dataset of type COMPOUND { seq: VLEN { int32 }, n: int32 }
|
||||
* inside the per-test file (H5fid) and write canonical data via H5DwriteVL.
|
||||
* Closes the vlen/compound/dataspace ids internally and returns only the
|
||||
* open dataset id; the caller closes the dataset and re-fetches the type
|
||||
* via H5Dget_type if needed.
|
||||
*/
|
||||
private long writeCompoundOfVlenDataset(String dsetName) throws Exception
|
||||
{
|
||||
long vlen_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long cmpd_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long dspace_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
|
||||
try {
|
||||
vlen_tid = H5.H5Tvlen_create(HDF5Constants.H5T_NATIVE_INT);
|
||||
assertTrue("writeCompoundOfVlenDataset: H5Tvlen_create: ", vlen_tid >= 0);
|
||||
|
||||
long hvlSize = H5.H5Tget_size(vlen_tid);
|
||||
long intSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT);
|
||||
long packedSize = hvlSize + intSize;
|
||||
cmpd_tid = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, packedSize);
|
||||
assertTrue("writeCompoundOfVlenDataset: H5Tcreate compound: ", cmpd_tid >= 0);
|
||||
H5.H5Tinsert(cmpd_tid, "seq", 0, vlen_tid);
|
||||
H5.H5Tinsert(cmpd_tid, "n", hvlSize, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tpack(cmpd_tid);
|
||||
|
||||
long[] dims = {2};
|
||||
dspace_id = H5.H5Screate_simple(1, dims, null);
|
||||
assertTrue("writeCompoundOfVlenDataset: H5Screate_simple: ", dspace_id >= 0);
|
||||
|
||||
dset_id = H5.H5Dcreate(H5fid, dsetName, cmpd_tid, dspace_id, HDF5Constants.H5P_DEFAULT,
|
||||
HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT);
|
||||
assertTrue("writeCompoundOfVlenDataset: H5Dcreate: ", dset_id >= 0);
|
||||
|
||||
ArrayList<Integer> seq0 = new ArrayList<>();
|
||||
seq0.add(1);
|
||||
seq0.add(2);
|
||||
seq0.add(3);
|
||||
ArrayList<Integer> seq1 = new ArrayList<>();
|
||||
seq1.add(5);
|
||||
seq1.add(6);
|
||||
|
||||
ArrayList[] write_data = new ArrayList[2];
|
||||
ArrayList<Object> rec0 = new ArrayList<>();
|
||||
rec0.add(seq0);
|
||||
rec0.add(Integer.valueOf(4));
|
||||
write_data[0] = rec0;
|
||||
ArrayList<Object> rec1 = new ArrayList<>();
|
||||
rec1.add(seq1);
|
||||
rec1.add(Integer.valueOf(7));
|
||||
write_data[1] = rec1;
|
||||
|
||||
H5.H5DwriteVL(dset_id, cmpd_tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, write_data);
|
||||
H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
|
||||
}
|
||||
finally {
|
||||
if (dspace_id >= 0)
|
||||
try {
|
||||
H5.H5Sclose(dspace_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (cmpd_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(cmpd_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (vlen_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(vlen_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
return dset_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 1-D dataset whose type is COMPOUND { seq: VLEN { int32 }, n: int32 }.
|
||||
* Uses the canonical calling pattern: pass ArrayList[] with null slots
|
||||
* and let the native code allocate each per-row record.
|
||||
*/
|
||||
@Test
|
||||
public void testH5Dread_compound_of_vlen()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
final int N_ROWS = 2;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_rd");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
assertTrue("testH5Dread_compound_of_vlen: H5Dget_type: ", file_type_id >= 0);
|
||||
|
||||
ArrayList[] read_data = new ArrayList[N_ROWS];
|
||||
H5.H5DreadVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, read_data);
|
||||
|
||||
assertNotNull("testH5Dread_compound_of_vlen: read_data[0] not null", read_data[0]);
|
||||
assertNotNull("testH5Dread_compound_of_vlen: read_data[1] not null", read_data[1]);
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 record has 2 members", 2, read_data[0].size());
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 1 record has 2 members", 2, read_data[1].size());
|
||||
|
||||
Object seq0obj = read_data[0].get(0);
|
||||
Object seq1obj = read_data[1].get(0);
|
||||
assertTrue("testH5Dread_compound_of_vlen: row 0 seq is ArrayList, got " +
|
||||
(seq0obj == null ? "null" : seq0obj.getClass().getName()),
|
||||
seq0obj instanceof ArrayList);
|
||||
assertTrue("testH5Dread_compound_of_vlen: row 1 seq is ArrayList, got " +
|
||||
(seq1obj == null ? "null" : seq1obj.getClass().getName()),
|
||||
seq1obj instanceof ArrayList);
|
||||
|
||||
ArrayList<?> seq0_read = (ArrayList<?>)seq0obj;
|
||||
ArrayList<?> seq1_read = (ArrayList<?>)seq1obj;
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 seq length", 3, seq0_read.size());
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 1 seq length", 2, seq1_read.size());
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 seq[0]", Integer.valueOf(1), seq0_read.get(0));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 seq[1]", Integer.valueOf(2), seq0_read.get(1));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 seq[2]", Integer.valueOf(3), seq0_read.get(2));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 1 seq[0]", Integer.valueOf(5), seq1_read.get(0));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 1 seq[1]", Integer.valueOf(6), seq1_read.get(1));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 0 n", Integer.valueOf(4), read_data[0].get(1));
|
||||
assertEquals("testH5Dread_compound_of_vlen: row 1 n", Integer.valueOf(7), read_data[1].get(1));
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5Dread_compound_of_vlen: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Round-trip a compound-of-vlen dataset through H5DwriteVL and H5DreadVL.
|
||||
* Reuses the writeCompoundOfVlenDataset helper to exercise the write path,
|
||||
* then reads back and asserts the full row contents.
|
||||
*/
|
||||
@Test
|
||||
public void testH5Dwrite_compound_of_vlen()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
final int N_ROWS = 2;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_wr");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
assertTrue("testH5Dwrite_compound_of_vlen: H5Dget_type: ", file_type_id >= 0);
|
||||
|
||||
ArrayList[] read_data = new ArrayList[N_ROWS];
|
||||
H5.H5DreadVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, read_data);
|
||||
|
||||
assertNotNull("testH5Dwrite_compound_of_vlen: read_data[0] not null", read_data[0]);
|
||||
assertNotNull("testH5Dwrite_compound_of_vlen: read_data[1] not null", read_data[1]);
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 record has 2 members", 2, read_data[0].size());
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 1 record has 2 members", 2, read_data[1].size());
|
||||
|
||||
ArrayList<?> seq0_read = (ArrayList<?>)read_data[0].get(0);
|
||||
ArrayList<?> seq1_read = (ArrayList<?>)read_data[1].get(0);
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 seq length", 3, seq0_read.size());
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 1 seq length", 2, seq1_read.size());
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 seq[0]", Integer.valueOf(1), seq0_read.get(0));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 seq[1]", Integer.valueOf(2), seq0_read.get(1));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 seq[2]", Integer.valueOf(3), seq0_read.get(2));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 1 seq[0]", Integer.valueOf(5), seq1_read.get(0));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 1 seq[1]", Integer.valueOf(6), seq1_read.get(1));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 0 n", Integer.valueOf(4), read_data[0].get(1));
|
||||
assertEquals("testH5Dwrite_compound_of_vlen: row 1 n", Integer.valueOf(7), read_data[1].get(1));
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5Dwrite_compound_of_vlen: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Negative tests for the API-level buffer-contract verification in H5DwriteVL.
|
||||
* Each supplies a malformed buffer for a COMPOUND { seq: VLEN int, n: int }
|
||||
* dataset and asserts a clean IllegalArgumentException is raised before any
|
||||
* native write, rather than a SIGSEGV or silent corruption.
|
||||
*/
|
||||
|
||||
/* Buffer shorter than the selection must be rejected (would otherwise overrun
|
||||
* the raw write buffer in H5Dwrite). */
|
||||
@Test
|
||||
public void testH5DwriteVL_undersized_buffer()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_wr_undersized");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
|
||||
// Dataset has 2 rows; supply only 1.
|
||||
ArrayList<Integer> seq = new ArrayList<>();
|
||||
seq.add(1);
|
||||
ArrayList<Object> rec = new ArrayList<>();
|
||||
rec.add(seq);
|
||||
rec.add(Integer.valueOf(2));
|
||||
ArrayList[] bad = new ArrayList[1];
|
||||
bad[0] = rec;
|
||||
|
||||
try {
|
||||
H5.H5DwriteVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, bad);
|
||||
fail("testH5DwriteVL_undersized_buffer: expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5DwriteVL_undersized_buffer: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A compound member whose Java type is wrong (String where an Integer is
|
||||
* expected) must be rejected instead of crashing in translate_atomic_wbuf. */
|
||||
@Test
|
||||
public void testH5DwriteVL_compound_wrong_member_type()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_wr_badmember");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
|
||||
ArrayList[] bad = new ArrayList[2];
|
||||
|
||||
ArrayList<Integer> seq0 = new ArrayList<>();
|
||||
seq0.add(1);
|
||||
ArrayList<Object> rec0 = new ArrayList<>();
|
||||
rec0.add(seq0);
|
||||
rec0.add(Integer.valueOf(4));
|
||||
bad[0] = rec0;
|
||||
|
||||
// row 1: the 'n' member is a String, not an Integer.
|
||||
ArrayList<Integer> seq1 = new ArrayList<>();
|
||||
seq1.add(5);
|
||||
ArrayList<Object> rec1 = new ArrayList<>();
|
||||
rec1.add(seq1);
|
||||
rec1.add("not an int");
|
||||
bad[1] = rec1;
|
||||
|
||||
try {
|
||||
H5.H5DwriteVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, bad);
|
||||
fail("testH5DwriteVL_compound_wrong_member_type: expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5DwriteVL_compound_wrong_member_type: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A VLEN member that is not an ArrayList (here a String) must be rejected
|
||||
* instead of being mis-read as a list. */
|
||||
@Test
|
||||
public void testH5DwriteVL_vlen_element_not_arraylist()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_wr_notlist");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
|
||||
ArrayList[] bad = new ArrayList[2];
|
||||
|
||||
// row 0: the 'seq' member should be an ArrayList but is a String.
|
||||
ArrayList<Object> rec0 = new ArrayList<>();
|
||||
rec0.add("not a list");
|
||||
rec0.add(Integer.valueOf(4));
|
||||
bad[0] = rec0;
|
||||
|
||||
ArrayList<Integer> seq1 = new ArrayList<>();
|
||||
seq1.add(5);
|
||||
ArrayList<Object> rec1 = new ArrayList<>();
|
||||
rec1.add(seq1);
|
||||
rec1.add(Integer.valueOf(7));
|
||||
bad[1] = rec1;
|
||||
|
||||
try {
|
||||
H5.H5DwriteVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, bad);
|
||||
fail("testH5DwriteVL_vlen_element_not_arraylist: expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5DwriteVL_vlen_element_not_arraylist: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A compound row with the wrong number of members must be rejected. */
|
||||
@Test
|
||||
public void testH5DwriteVL_compound_wrong_member_count()
|
||||
{
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long file_type_id = HDF5Constants.H5I_INVALID_HID;
|
||||
|
||||
try {
|
||||
dset_id = writeCompoundOfVlenDataset("cmpd_of_vlen_wr_badcount");
|
||||
file_type_id = H5.H5Dget_type(dset_id);
|
||||
|
||||
ArrayList[] bad = new ArrayList[2];
|
||||
|
||||
// row 0: only one member instead of two ('n' is missing).
|
||||
ArrayList<Integer> seq0 = new ArrayList<>();
|
||||
seq0.add(1);
|
||||
ArrayList<Object> rec0 = new ArrayList<>();
|
||||
rec0.add(seq0);
|
||||
bad[0] = rec0;
|
||||
|
||||
ArrayList<Integer> seq1 = new ArrayList<>();
|
||||
seq1.add(5);
|
||||
ArrayList<Object> rec1 = new ArrayList<>();
|
||||
rec1.add(seq1);
|
||||
rec1.add(Integer.valueOf(7));
|
||||
bad[1] = rec1;
|
||||
|
||||
try {
|
||||
H5.H5DwriteVL(dset_id, file_type_id, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, bad);
|
||||
fail("testH5DwriteVL_compound_wrong_member_count: expected IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5DwriteVL_compound_wrong_member_count: " + err);
|
||||
}
|
||||
finally {
|
||||
if (file_type_id >= 0)
|
||||
try {
|
||||
H5.H5Tclose(file_type_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 1-D dataset whose type is VLEN { COMPOUND { A: int, B: int } }. The
|
||||
* caller passes a freshly allocated array with null row slots, which is the
|
||||
* canonical read pattern: the JNI installs a freshly allocated ArrayList into
|
||||
* each slot. Exercises the translate_rbuf H5T_VLEN top-level case for a
|
||||
* compound element type.
|
||||
*/
|
||||
@Test
|
||||
public void testH5Dread_vlen_of_compound()
|
||||
{
|
||||
long cmpd_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long vlen_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long dspace_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
final int N_ROWS = 2;
|
||||
|
||||
try {
|
||||
long intSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT);
|
||||
|
||||
cmpd_tid = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, 2 * intSize);
|
||||
H5.H5Tinsert(cmpd_tid, "A", 0, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tinsert(cmpd_tid, "B", intSize, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tpack(cmpd_tid);
|
||||
|
||||
vlen_tid = H5.H5Tvlen_create(cmpd_tid);
|
||||
long[] dims = {N_ROWS};
|
||||
dspace_id = H5.H5Screate_simple(1, dims, null);
|
||||
|
||||
dset_id = H5.H5Dcreate(H5fid, "vlen_of_cmpd_rd", vlen_tid, dspace_id, HDF5Constants.H5P_DEFAULT,
|
||||
HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT);
|
||||
assertTrue("testH5Dread_vlen_of_compound: H5Dcreate: ", dset_id >= 0);
|
||||
|
||||
// row 0: 1 element [ { A=1, B=2 } ]
|
||||
// row 1: 2 elements [ { A=3, B=4 }, { A=5, B=6 } ]
|
||||
ArrayList<Object> row0_elem0 = new ArrayList<>();
|
||||
row0_elem0.add(Integer.valueOf(1));
|
||||
row0_elem0.add(Integer.valueOf(2));
|
||||
ArrayList<Object> row0 = new ArrayList<>();
|
||||
row0.add(row0_elem0);
|
||||
|
||||
ArrayList<Object> row1_elem0 = new ArrayList<>();
|
||||
row1_elem0.add(Integer.valueOf(3));
|
||||
row1_elem0.add(Integer.valueOf(4));
|
||||
ArrayList<Object> row1_elem1 = new ArrayList<>();
|
||||
row1_elem1.add(Integer.valueOf(5));
|
||||
row1_elem1.add(Integer.valueOf(6));
|
||||
ArrayList<Object> row1 = new ArrayList<>();
|
||||
row1.add(row1_elem0);
|
||||
row1.add(row1_elem1);
|
||||
|
||||
ArrayList[] write_data = new ArrayList[N_ROWS];
|
||||
write_data[0] = row0;
|
||||
write_data[1] = row1;
|
||||
|
||||
H5.H5DwriteVL(dset_id, vlen_tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, write_data);
|
||||
H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
|
||||
|
||||
// Freshly allocated array with null row slots; the JNI fills each slot.
|
||||
ArrayList[] read_data = new ArrayList[N_ROWS];
|
||||
H5.H5DreadVL(dset_id, vlen_tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, read_data);
|
||||
|
||||
assertNotNull("testH5Dread_vlen_of_compound: row 0 not null", read_data[0]);
|
||||
assertNotNull("testH5Dread_vlen_of_compound: row 1 not null", read_data[1]);
|
||||
assertEquals("testH5Dread_vlen_of_compound: row 0 has 1 element", 1, read_data[0].size());
|
||||
assertEquals("testH5Dread_vlen_of_compound: row 1 has 2 elements", 2, read_data[1].size());
|
||||
|
||||
ArrayList<?> r0e0 = (ArrayList<?>)read_data[0].get(0);
|
||||
assertEquals("row 0 elem 0 A", Integer.valueOf(1), r0e0.get(0));
|
||||
assertEquals("row 0 elem 0 B", Integer.valueOf(2), r0e0.get(1));
|
||||
|
||||
ArrayList<?> r1e0 = (ArrayList<?>)read_data[1].get(0);
|
||||
assertEquals("row 1 elem 0 A", Integer.valueOf(3), r1e0.get(0));
|
||||
assertEquals("row 1 elem 0 B", Integer.valueOf(4), r1e0.get(1));
|
||||
|
||||
ArrayList<?> r1e1 = (ArrayList<?>)read_data[1].get(1);
|
||||
assertEquals("row 1 elem 1 A", Integer.valueOf(5), r1e1.get(0));
|
||||
assertEquals("row 1 elem 1 B", Integer.valueOf(6), r1e1.get(1));
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5Dread_vlen_of_compound: " + err);
|
||||
}
|
||||
finally {
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dspace_id >= 0)
|
||||
try {
|
||||
H5.H5Sclose(dspace_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (vlen_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(vlen_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (cmpd_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(cmpd_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 1-D dataset whose type is VLEN { COMPOUND { id: int, sub: COMPOUND { P: int, Q: int } } }.
|
||||
* Per-row canonical shape (per testH5Dwrite_readCompound contract):
|
||||
* row r ArrayList of vlen elements
|
||||
* each element is ArrayList of 2 members [Integer id, ArrayList sub]
|
||||
* sub is ArrayList of 2 members [Integer P, Integer Q]
|
||||
*/
|
||||
@Test
|
||||
public void testH5Dread_vlen_of_nested_compound()
|
||||
{
|
||||
long inner_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long outer_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long vlen_tid = HDF5Constants.H5I_INVALID_HID;
|
||||
long dspace_id = HDF5Constants.H5I_INVALID_HID;
|
||||
long dset_id = HDF5Constants.H5I_INVALID_HID;
|
||||
final int N_ROWS = 2;
|
||||
|
||||
try {
|
||||
long intSize = H5.H5Tget_size(HDF5Constants.H5T_NATIVE_INT);
|
||||
|
||||
// inner = compound { P:int, Q:int }
|
||||
inner_tid = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, 2 * intSize);
|
||||
H5.H5Tinsert(inner_tid, "P", 0, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tinsert(inner_tid, "Q", intSize, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tpack(inner_tid);
|
||||
|
||||
// outer = compound { id:int, sub:inner }
|
||||
long innerSize = H5.H5Tget_size(inner_tid);
|
||||
outer_tid = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, intSize + innerSize);
|
||||
H5.H5Tinsert(outer_tid, "id", 0, HDF5Constants.H5T_NATIVE_INT);
|
||||
H5.H5Tinsert(outer_tid, "sub", intSize, inner_tid);
|
||||
H5.H5Tpack(outer_tid);
|
||||
|
||||
// vlen of outer
|
||||
vlen_tid = H5.H5Tvlen_create(outer_tid);
|
||||
long[] dims = {N_ROWS};
|
||||
dspace_id = H5.H5Screate_simple(1, dims, null);
|
||||
|
||||
dset_id =
|
||||
H5.H5Dcreate(H5fid, "vlen_of_nested_cmpd", vlen_tid, dspace_id, HDF5Constants.H5P_DEFAULT,
|
||||
HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT);
|
||||
assertTrue("testH5Dread_vlen_of_nested_compound: H5Dcreate: ", dset_id >= 0);
|
||||
|
||||
// row 0: 1 element [ { id=1, sub={ P=2, Q=3 } } ]
|
||||
// row 1: 2 elements [ { id=4, sub={ P=5, Q=6 } }, { id=7, sub={ P=8, Q=9 } } ]
|
||||
ArrayList<Object> row0_elem0_sub = new ArrayList<>();
|
||||
row0_elem0_sub.add(Integer.valueOf(2));
|
||||
row0_elem0_sub.add(Integer.valueOf(3));
|
||||
ArrayList<Object> row0_elem0 = new ArrayList<>();
|
||||
row0_elem0.add(Integer.valueOf(1));
|
||||
row0_elem0.add(row0_elem0_sub);
|
||||
ArrayList<Object> row0 = new ArrayList<>();
|
||||
row0.add(row0_elem0);
|
||||
|
||||
ArrayList<Object> row1_elem0_sub = new ArrayList<>();
|
||||
row1_elem0_sub.add(Integer.valueOf(5));
|
||||
row1_elem0_sub.add(Integer.valueOf(6));
|
||||
ArrayList<Object> row1_elem0 = new ArrayList<>();
|
||||
row1_elem0.add(Integer.valueOf(4));
|
||||
row1_elem0.add(row1_elem0_sub);
|
||||
ArrayList<Object> row1_elem1_sub = new ArrayList<>();
|
||||
row1_elem1_sub.add(Integer.valueOf(8));
|
||||
row1_elem1_sub.add(Integer.valueOf(9));
|
||||
ArrayList<Object> row1_elem1 = new ArrayList<>();
|
||||
row1_elem1.add(Integer.valueOf(7));
|
||||
row1_elem1.add(row1_elem1_sub);
|
||||
ArrayList<Object> row1 = new ArrayList<>();
|
||||
row1.add(row1_elem0);
|
||||
row1.add(row1_elem1);
|
||||
|
||||
ArrayList[] write_data = new ArrayList[N_ROWS];
|
||||
write_data[0] = row0;
|
||||
write_data[1] = row1;
|
||||
|
||||
H5.H5DwriteVL(dset_id, vlen_tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, write_data);
|
||||
H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
|
||||
|
||||
ArrayList[] read_data = new ArrayList[N_ROWS];
|
||||
H5.H5DreadVL(dset_id, vlen_tid, HDF5Constants.H5S_ALL, HDF5Constants.H5S_ALL,
|
||||
HDF5Constants.H5P_DEFAULT, read_data);
|
||||
|
||||
assertNotNull("row 0 not null", read_data[0]);
|
||||
assertNotNull("row 1 not null", read_data[1]);
|
||||
assertEquals("row 0 has 1 element", 1, read_data[0].size());
|
||||
assertEquals("row 1 has 2 elements", 2, read_data[1].size());
|
||||
|
||||
ArrayList<?> r0e0 = (ArrayList<?>)read_data[0].get(0);
|
||||
assertEquals("row 0 elem 0 has 2 members", 2, r0e0.size());
|
||||
assertEquals("row 0 elem 0 id", Integer.valueOf(1), r0e0.get(0));
|
||||
ArrayList<?> r0e0sub = (ArrayList<?>)r0e0.get(1);
|
||||
assertEquals("row 0 elem 0 sub has 2 members", 2, r0e0sub.size());
|
||||
assertEquals("row 0 elem 0 sub.P", Integer.valueOf(2), r0e0sub.get(0));
|
||||
assertEquals("row 0 elem 0 sub.Q", Integer.valueOf(3), r0e0sub.get(1));
|
||||
|
||||
ArrayList<?> r1e1 = (ArrayList<?>)read_data[1].get(1);
|
||||
assertEquals("row 1 elem 1 has 2 members", 2, r1e1.size());
|
||||
assertEquals("row 1 elem 1 id", Integer.valueOf(7), r1e1.get(0));
|
||||
ArrayList<?> r1e1sub = (ArrayList<?>)r1e1.get(1);
|
||||
assertEquals("row 1 elem 1 sub.P", Integer.valueOf(8), r1e1sub.get(0));
|
||||
assertEquals("row 1 elem 1 sub.Q", Integer.valueOf(9), r1e1sub.get(1));
|
||||
}
|
||||
catch (Throwable err) {
|
||||
err.printStackTrace();
|
||||
fail("testH5Dread_vlen_of_nested_compound: " + err);
|
||||
}
|
||||
finally {
|
||||
if (dset_id >= 0)
|
||||
try {
|
||||
H5.H5Dclose(dset_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (dspace_id >= 0)
|
||||
try {
|
||||
H5.H5Sclose(dspace_id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (vlen_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(vlen_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (outer_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(outer_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
if (inner_tid >= 0)
|
||||
try {
|
||||
H5.H5Tclose(inner_tid);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ public class TestH5Drw {
|
||||
@Test
|
||||
public void testH5Dread_128bit_floats()
|
||||
{
|
||||
byte[][][] dset_data = new byte[DIM_X][DIM128_Y][8];
|
||||
byte[][][] dset_data = new byte[DIM_X][DIM128_Y][16];
|
||||
|
||||
try {
|
||||
openH5file(H5_FLTS_FILE, DATASETF128);
|
||||
|
||||
@@ -14,15 +14,25 @@ JUnit version 4.13.2
|
||||
.testH5Dfill_null
|
||||
.testH5Dget_storage_size_empty
|
||||
.testH5Diterate
|
||||
.testH5DwriteVL_compound_wrong_member_type
|
||||
.testH5Dget_access_plist
|
||||
.testH5Dread_vlen_of_nested_compound
|
||||
.testH5DArray_string_buffer_flat_StringArray
|
||||
.testH5Dget_space_closed
|
||||
.testH5DArray_string_buffer_flat_StringArray_write
|
||||
.testH5DArray_string_buffer
|
||||
.testH5Dread_vlen_of_compound
|
||||
.testH5Dread_compound_of_vlen
|
||||
.testH5Dget_space_status
|
||||
.testH5DwriteVL_compound_wrong_member_count
|
||||
.testH5Dvlen_write_read
|
||||
.testH5Dget_space
|
||||
.testH5DwriteVL_vlen_element_not_arraylist
|
||||
.testH5Dget_type_closed
|
||||
.testH5Dwrite_compound_of_vlen
|
||||
.testH5DwriteVL_undersized_buffer
|
||||
|
||||
Time: XXXX
|
||||
|
||||
OK (22 tests)
|
||||
OK (32 tests)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user