mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-25 04:09:44 +03:00
* 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>
155 lines
7.0 KiB
C
155 lines
7.0 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the LICENSE file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#ifndef H5UTIL_H__
|
|
#define H5UTIL_H__
|
|
|
|
#include "h5jni.h"
|
|
|
|
#ifndef SUCCEED
|
|
#define SUCCEED 0
|
|
#endif
|
|
|
|
#ifndef FAIL
|
|
#define FAIL (-1)
|
|
#endif
|
|
|
|
typedef struct h5str_t {
|
|
char *s;
|
|
size_t max; /* the allocated size of the string */
|
|
} h5str_t;
|
|
|
|
extern void h5str_new(h5str_t *str, size_t len);
|
|
extern void h5str_free(h5str_t *str);
|
|
extern void h5str_resize(h5str_t *str, size_t new_len);
|
|
extern char *h5str_append(h5str_t *str, const char *cstr);
|
|
extern htri_t h5str_detect_vlen(hid_t tid);
|
|
extern size_t h5str_convert(JNIEnv *env, char **in_str, hid_t container, hid_t tid, void *out_buf,
|
|
size_t out_buf_offset);
|
|
extern int h5str_sprint_old_reference(JNIEnv *env, h5str_t *out_str, hid_t region_obj, void *ref_buf);
|
|
extern int h5str_sprint_reference(JNIEnv *env, h5str_t *out_str, void *ref_p);
|
|
extern size_t h5str_sprintf(JNIEnv *env, h5str_t *out_str, hid_t container, hid_t tid, void *in_buf,
|
|
int expand_data);
|
|
extern void h5str_array_free(char **strs, size_t len);
|
|
extern int h5str_dump_simple_dset(JNIEnv *env, FILE *stream, hid_t dset, int binary_order);
|
|
extern int h5str_dump_simple_mem(JNIEnv *env, FILE *stream, hid_t attr, int binary_order);
|
|
|
|
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, 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, 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
|
|
* to interpret the input to h5str_convert.
|
|
*/
|
|
#define H5_COMPOUND_BEGIN_INDICATOR "{"
|
|
#define H5_COMPOUND_END_INDICATOR "}"
|
|
#define H5_ARRAY_BEGIN_INDICATOR "["
|
|
#define H5_ARRAY_END_INDICATOR "]"
|
|
#define H5_VLEN_BEGIN_INDICATOR "("
|
|
#define H5_VLEN_END_INDICATOR ")"
|
|
|
|
/*
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5AreadComplex
|
|
* Signature: (JJ[Ljava/lang/String;)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5AreadComplex(JNIEnv *, jclass, jlong, jlong, jobjectArray);
|
|
|
|
/*
|
|
* Copies the content of one dataset to another dataset
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5Acopy
|
|
* Signature: (JJ)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Acopy(JNIEnv *, jclass, jlong, jlong);
|
|
|
|
/*
|
|
* Copies the content of one dataset to another dataset
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5Dcopy
|
|
* Signature: (JJ)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Dcopy(JNIEnv *, jclass, jlong, jlong);
|
|
|
|
/*
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5Gget_obj_info_full
|
|
* Signature: (JLjava/lang/String;[Ljava/lang/String;[I[I[J[JIII)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1full(JNIEnv *, jclass, jlong, jstring,
|
|
jobjectArray, jintArray, jintArray,
|
|
jlongArray, jobjectArray, jint, jint,
|
|
jint);
|
|
|
|
/*
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5Gget_obj_info_max
|
|
* Signature: (J[Ljava/lang/String;[I[I[JJI)I
|
|
*/
|
|
JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1max(JNIEnv *, jclass, jlong, jobjectArray,
|
|
jintArray, jintArray, jlongArray, jlong,
|
|
jint);
|
|
|
|
/*
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5export_dataset
|
|
* Signature: (Ljava/lang/String;JLjava/lang/String;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_hdf_hdf5lib_H5_H5export_1dataset(JNIEnv *, jclass, jstring, jlong, jstring, jint);
|
|
|
|
/*
|
|
* Class: hdf_hdf5lib_H5
|
|
* Method: H5export_attribute
|
|
* Signature: (Ljava/lang/String;JLjava/lang/String;I)V
|
|
*/
|
|
JNIEXPORT void JNICALL Java_hdf_hdf5lib_H5_H5export_1attribute(JNIEnv *, jclass, jstring, jlong, jstring,
|
|
jint);
|
|
|
|
#endif /* H5UTIL_H__ */
|