Files
Matt L 355f67ac37 Close datatype IDs derived from memory type in the JNI translation helpers (#6594)
* Close datatype IDs derived from the memory type in the JNI translate helpers

The object-tree read/write helpers in h5util.c derive a base datatype from
the memory type with H5Tget_super() for the variable-length, array and
complex classes, but never closed it. Because an hid_t is not reclaimed when
the native method returns, every read or write of such data leaked at least
one datatype ID for the lifetime of the process, and nested types leaked
one per level.

This PR updates the helpers to close the derived type in their done: blocks,
which covers both the success and the error paths, and to reset the id in the
compound loops to avoid the potential for double closes.

It also has the helpers release the class references that the per-element
helpers look up on entry. These are local references, so they were reclaimed
when the enclosing native method returned, but a compound read calls the helper
once per member per element and held one set per call until then. Releasing
them at the single exit bounds the count of references to the recursion depth.

* Add CHANGELOG entry for the JNI datatype ID leak fix

* Restrict the derived datatype close guards to strictly positive IDs

hid_t 0 is not a valid datatype ID, so H5Tclose(0) would fail.

* Revert "Restrict the derived datatype close guards to strictly positive IDs"

An hid_t of 0 not being a valid ID is a property of the current H5I
encoding rather than a documented guarantee, so the JNI helpers should
not depend on it.
2026-09-11 09:59:03 -05:00

5785 lines
207 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "hdf5.h"
#include "h5util.h"
/* size of hyperslab buffer when a dataset is bigger than H5TOOLS_MALLOCSIZE */
hsize_t H5TOOLS_BUFSIZE = (32 * 1024 * 1024); /* 32 MB */
int H5TOOLS_TEXT_BLOCK = 16; /* Number of elements on a line in a text export file */
/*
* Pointer to the JNI's Virtual Machine; used for callback functions.
*/
JavaVM *jvm;
jobject copy_callback;
jobject close_callback;
jobject create_callback;
jobject compare_callback;
jobject get_callback;
jobject set_callback;
jobject delete_callback;
H5E_auto2_t efunc;
void *edata;
/********************/
/* Local Prototypes */
/********************/
int h5str_old_region_dataset(JNIEnv *env, h5str_t *out_str, hid_t container, void *ref_buf, int expand_data);
int h5str_region_dataset(JNIEnv *env, h5str_t *out_str, H5R_ref_t *ref_vp, int expand_data);
static int h5str_dump_region_blocks(JNIEnv *env, h5str_t *str, hid_t region, hid_t region_obj,
int expand_data);
static int h5str_dump_region_points(JNIEnv *env, h5str_t *str, hid_t region, hid_t region_obj,
int expand_data);
static int h5str_dump_region_attribute(JNIEnv *env, h5str_t *str, hid_t region_id);
static int h5str_is_zero(const void *_mem, size_t size);
static hid_t h5str_get_native_type(hid_t type);
static hid_t h5str_get_little_endian_type(hid_t type);
static hid_t h5str_get_big_endian_type(hid_t type);
static htri_t h5str_detect_vlen_str(hid_t tid);
static int h5str_dump_simple_data(JNIEnv *env, FILE *stream, hid_t container, hid_t type, void *_mem,
hsize_t nelmts);
static int h5str_render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem,
hsize_t block_nelmts);
static int render_bin_output_region_data_blocks(FILE *stream, hid_t region_id, hid_t container, int ndims,
hid_t type_id, hssize_t nblocks, hsize_t *ptdata);
static int render_bin_output_region_blocks(FILE *stream, hid_t region_space, hid_t region_id,
hid_t container);
static int render_bin_output_region_data_points(FILE *stream, hid_t region_space, hid_t region_id,
hid_t container, int ndims, hid_t type_id, hssize_t npoints,
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,
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, 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"
#define H5_TOOLS_DATASET "DATASET"
#define H5_TOOLS_DATATYPE "DATATYPE"
#define H5_TOOLS_MAP "MAP"
/** frees memory held by array of strings */
void
h5str_array_free(char **strs, size_t len)
{
size_t i;
if (!strs || len <= 0)
return;
for (i = 0; i < len; i++) {
if (strs[i])
free(strs[i]);
} /* for (i=0; i<n; i++)*/
free(strs);
} /* end h5str_array_free */
/** allocate a new str with given length */
void
h5str_new(h5str_t *str, size_t len)
{
if (str && len > 0) {
str->s = (char *)malloc(len);
str->max = len;
str->s[0] = '\0';
} /* end if */
} /* end h5str_new */
/** free string memory */
void
h5str_free(h5str_t *str)
{
if (str && str->max > 0) {
free(str->s);
memset(str, 0, sizeof(h5str_t));
} /* end if */
} /* end h5str_free */
/** reset the max size of the string */
/*
* TODO: no error return. malloc can fail.
*/
void
h5str_resize(h5str_t *str, size_t new_len)
{
char *new_str;
if (!str || new_len <= 0 || str->max == new_len)
return;
if (NULL == (new_str = (char *)malloc(new_len)))
return;
if (new_len > str->max) /* increase memory */
strcpy(new_str, str->s);
else
strncpy(new_str, str->s, new_len - 1);
free(str->s);
str->s = new_str;
str->max = new_len;
} /* end h5str_resize */
/* appends a copy of the string pointed to by cstr to the h5str.
Return Value:
the char string point to str->s
*/
char *
h5str_append(h5str_t *str, const char *cstr)
{
size_t len;
if (!str)
return NULL;
else if (!cstr)
return str->s;
len = strlen(str->s) + strlen(cstr);
while (len >= str->max) /* not enough to hold the new string, double the space */
{
h5str_resize(str, str->max * 2);
}
return strcat(str->s, cstr);
} /* end h5str_append */
/*
* Converts the given data point string into a real data point.
*
* Returns:
* SUCCESS: Length of string token processed
* FAILURE: 0
*/
size_t
h5str_convert(JNIEnv *env, char **in_str, hid_t container, hid_t tid, void *out_buf, size_t out_buf_offset)
{
unsigned char *ucptr = NULL;
char fmt_llong[8], fmt_ullong[8];
H5T_class_t tclass = H5T_NO_CLASS;
const char delimiter[] = " ," H5_COMPOUND_BEGIN_INDICATOR H5_COMPOUND_END_INDICATOR
H5_ARRAY_BEGIN_INDICATOR H5_ARRAY_END_INDICATOR H5_VLEN_BEGIN_INDICATOR H5_VLEN_END_INDICATOR;
size_t retVal = 0;
size_t typeSize = 0;
hid_t mtid = H5I_INVALID_HID;
char *this_str = NULL;
char *cptr = NULL;
char *token;
int n;
if (!in_str)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "h5str_convert: in_str is NULL");
if (!out_buf)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "h5str_convert: out_buf is NULL");
this_str = *in_str;
cptr = &(((char *)out_buf)[out_buf_offset]);
ucptr = &(((unsigned char *)out_buf)[out_buf_offset]);
if (H5T_NO_CLASS == (tclass = H5Tget_class(tid)))
H5_LIBRARY_ERROR(ENVONLY);
if (!(typeSize = H5Tget_size(tid)))
H5_LIBRARY_ERROR(ENVONLY);
/* Build default formats for long long types */
if (!fmt_llong[0]) {
if (snprintf(fmt_llong, sizeof(fmt_llong), "%%lld") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_convert: snprintf failure");
if (snprintf(fmt_ullong, sizeof(fmt_ullong), "%%llu") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_convert: snprintf failure");
} /* end if */
switch (tclass) {
case H5T_FLOAT: {
token = strtok(this_str, delimiter);
switch (typeSize) {
case sizeof(float): {
float tmp_float = 0.0f;
sscanf(token, "%f", &tmp_float);
memcpy(cptr, &tmp_float, sizeof(float));
break;
}
case sizeof(double): {
double tmp_double = 0.0;
sscanf(token, "%lf", &tmp_double);
memcpy(cptr, &tmp_double, sizeof(double));
break;
}
#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE
case sizeof(long double): {
long double tmp_ldouble = 0.0L;
sscanf(token, "%Lg", &tmp_ldouble);
memcpy(cptr, &tmp_ldouble, sizeof(long double));
break;
}
#endif
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY,
"h5str_convert: floating-point datatype size didn't match any of expected sizes");
break;
}
retVal = typeSize;
break;
}
case H5T_STRING: {
size_t len = strlen(this_str);
if (len > 0) {
strncpy(cptr, this_str, typeSize);
cptr[typeSize - 1] = '\0';
retVal = typeSize;
}
else {
cptr = NULL;
}
break;
}
case H5T_INTEGER: {
H5T_sign_t nsign = H5T_SGN_ERROR;
if (H5T_SGN_ERROR == (nsign = H5Tget_sign(tid)))
H5_LIBRARY_ERROR(ENVONLY);
token = strtok(this_str, delimiter);
switch (typeSize) {
case sizeof(char): {
unsigned char tmp_uchar = 0;
signed char tmp_char = 0;
if (H5T_SGN_NONE == nsign) {
sscanf(token, "%hhu", &tmp_uchar);
memcpy(cptr, &tmp_uchar, sizeof(unsigned char));
}
else {
sscanf(token, "%hhd", &tmp_char);
memcpy(cptr, &tmp_char, sizeof(char));
}
break;
}
case sizeof(short): {
unsigned short tmp_ushort = 0;
short tmp_short = 0;
if (H5T_SGN_NONE == nsign) {
sscanf(token, "%hu", &tmp_ushort);
memcpy(cptr, &tmp_ushort, sizeof(unsigned short));
}
else {
sscanf(token, "%hd", &tmp_short);
memcpy(cptr, &tmp_short, sizeof(short));
}
break;
}
case sizeof(int): {
unsigned int tmp_uint = 0;
int tmp_int = 0;
if (H5T_SGN_NONE == nsign) {
sscanf(token, "%u", &tmp_uint);
memcpy(cptr, &tmp_uint, sizeof(unsigned int));
}
else {
sscanf(token, "%d", &tmp_int);
memcpy(cptr, &tmp_int, sizeof(int));
}
break;
}
#if H5_SIZEOF_LONG != H5_SIZEOF_INT
case sizeof(long): {
unsigned long tmp_ulong = 0;
long tmp_long = 0;
if (H5T_SGN_NONE == nsign) {
sscanf(token, "%lu", &tmp_ulong);
memcpy(cptr, &tmp_ulong, sizeof(unsigned long));
}
else {
sscanf(token, "%ld", &tmp_long);
memcpy(cptr, &tmp_long, sizeof(long));
}
break;
}
#endif
#if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG
case sizeof(long long): {
unsigned long long tmp_ullong = 0;
long long tmp_llong = 0;
if (H5T_SGN_NONE == nsign) {
sscanf(token, fmt_ullong, &tmp_ullong);
memcpy(cptr, &tmp_ullong, sizeof(unsigned long long));
}
else {
sscanf(token, fmt_llong, &tmp_llong);
memcpy(cptr, &tmp_llong, sizeof(long long));
}
break;
}
#endif
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY, "h5str_convert: integer datatype size didn't match any of expected sizes");
break;
}
retVal = typeSize;
break;
}
case H5T_COMPOUND: {
unsigned i;
size_t member_offset;
if ((n = H5Tget_nmembers(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Skip whitespace and compound indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == '{')
this_str++;
while (*this_str == ' ')
this_str++;
for (i = 0; i < (unsigned)n; i++) {
member_offset = H5Tget_member_offset(tid, i);
if ((mtid = H5Tget_member_type(tid, i)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, member_offset)) {
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
goto done;
}
/* Skip whitespace and commas */
while (*this_str == ' ')
this_str++;
if (*this_str == ',')
this_str++;
while (*this_str == ' ')
this_str++;
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
}
/* Skip whitespace and compound indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == '}')
this_str++;
while (*this_str == ' ')
this_str++;
retVal = typeSize * (size_t)n;
break;
}
/* TODO handle reference writing */
case H5T_REFERENCE:
cptr = NULL;
break;
case H5T_ENUM: {
void *value = NULL;
unsigned char tmp_uchar = 0;
unsigned short tmp_ushort = 0;
unsigned int tmp_uint = 0;
#if H5_SIZEOF_LONG != H5_SIZEOF_INT
unsigned long tmp_ulong = 0;
#endif
#if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG
unsigned long long tmp_ullong = 0;
#endif
token = strtok(this_str, delimiter);
switch (typeSize) {
case sizeof(char): {
value = &tmp_uchar;
break;
}
case sizeof(short): {
value = &tmp_ushort;
break;
}
#if H5_SIZEOF_LONG != H5_SIZEOF_INT
case sizeof(long): {
value = &tmp_ulong;
break;
}
#endif
#if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG
case sizeof(long long): {
value = &tmp_ullong;
break;
}
#endif
default: {
value = &tmp_uint;
break;
}
}
if (H5Tenum_valueof(tid, token, value) < 0)
H5_LIBRARY_ERROR(ENVONLY);
memcpy(ucptr, value, typeSize);
retVal = typeSize;
break;
}
case H5T_ARRAY: {
hsize_t i, dims[H5S_MAX_RANK], total_elmts;
size_t baseTypeSize;
int rank = 0;
/* Skip whitespace and array indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == '[')
this_str++;
while (*this_str == ' ')
this_str++;
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseTypeSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
if ((rank = H5Tget_array_ndims(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tget_array_dims2(tid, dims) < 0)
H5_LIBRARY_ERROR(ENVONLY);
for (i = 0, total_elmts = 1; i < (hsize_t)rank; i++)
total_elmts *= dims[i];
for (i = 0; i < total_elmts; i++) {
if (!(h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, i * baseTypeSize))) {
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
goto done;
}
/* Skip whitespace and commas */
while (*this_str == ' ')
this_str++;
if (*this_str == ',')
this_str++;
while (*this_str == ' ')
this_str++;
}
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
/* Skip whitespace and array indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == ']')
this_str++;
while (*this_str == ' ')
this_str++;
retVal = typeSize * total_elmts;
break;
}
case H5T_VLEN: {
size_t i, baseTypeSize;
hvl_t *vl_buf = (hvl_t *)out_buf;
char cur_char;
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseTypeSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
if (NULL == (vl_buf->p = malloc(baseTypeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_convert: failed to allocate vlen buffer");
vl_buf->len = 1;
/* Skip whitespace and vlen indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == '(')
this_str++;
while (*this_str == ' ')
this_str++;
cur_char = *this_str;
for (i = 0; cur_char != ')' && cur_char != '\0'; i++) {
if (i >= vl_buf->len) {
char *tmp_realloc;
if (NULL == (tmp_realloc = (char *)realloc(vl_buf->p, vl_buf->len * 2 * baseTypeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_convert: failed to reallocate vlen buffer");
vl_buf->len *= 2;
vl_buf->p = tmp_realloc;
}
if (!(h5str_convert(ENVONLY, &this_str, container, mtid, vl_buf->p, i * baseTypeSize))) {
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
vl_buf->len = i;
goto done;
}
/* Skip whitespace and commas */
while (*this_str == ' ')
this_str++;
if (*this_str == ',')
this_str++;
while (*this_str == ' ')
this_str++;
}
vl_buf->len = i;
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
/* Skip whitespace and vlen indicators */
while (*this_str == ' ')
this_str++;
if (*this_str == ')')
this_str++;
while (*this_str == ' ')
this_str++;
retVal = typeSize;
break;
}
case H5T_COMPLEX: {
size_t baseTypeSize;
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseTypeSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
/* Convert real part */
if (!(h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, 0))) {
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
goto done;
}
/* Skip any whitespace */
while (*this_str == ' ')
this_str++;
/* Convert imaginary part */
if (!(h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, baseTypeSize))) {
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
goto done;
}
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
retVal = typeSize;
break;
}
case H5T_NCLASSES:
case H5T_NO_CLASS: {
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_convert: invalid datatype class");
break;
}
case H5T_TIME:
case H5T_BITFIELD:
case H5T_OPAQUE:
default: {
/* All other types get copied raw */
memcpy(ucptr, this_str, typeSize);
retVal = typeSize;
break;
}
} /* end switch */
done:
if (mtid >= 0)
H5Tclose(mtid);
return retVal;
} /* end h5str_convert */
/*-------------------------------------------------------------------------
* Function: h5str_sprint_old_reference
*
* Purpose: Object reference -- show the name of the 1.10 referenced object.
*
* Return: SUCCEED or FAIL
*-------------------------------------------------------------------------
*/
int
h5str_sprint_old_reference(JNIEnv *env, h5str_t *out_str, hid_t region_obj, void *ref_buf)
{
char ref_name[1024];
int ret_value = FAIL;
if ((H5Rget_name(region_obj, H5R_DATASET_REGION, ref_buf, (char *)ref_name, 1024)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_append(out_str, ref_name))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
ret_value = SUCCEED;
done:
return ret_value;
} /* h5str_sprint_reference */
/*-------------------------------------------------------------------------
* Function: h5str_sprint_reference
*
* Purpose: Object reference -- show the name of the referenced object.
*
* Return: SUCCEED or FAIL
*-------------------------------------------------------------------------
*/
int
h5str_sprint_reference(JNIEnv *env, h5str_t *out_str, void *ref_p)
{
ssize_t buf_size;
char *ref_name = NULL;
H5R_ref_t *ref_vp = (H5R_ref_t *)ref_p;
int ret_value = FAIL;
buf_size = H5Rget_file_name(ref_vp, NULL, 0);
if (buf_size > 0) {
ref_name = (char *)malloc(sizeof(char) * (size_t)buf_size + 1);
if (H5Rget_file_name(ref_vp, ref_name, (size_t)buf_size + 1) >= 0) {
ref_name[buf_size] = '\0';
if (!h5str_append(out_str, ref_name))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
free(ref_name);
ref_name = NULL;
}
buf_size = H5Rget_obj_name(ref_vp, H5P_DEFAULT, NULL, 0);
if (buf_size > 0) {
ref_name = (char *)malloc(sizeof(char) * (size_t)buf_size + 1);
if (H5Rget_obj_name(ref_vp, H5P_DEFAULT, ref_name, (size_t)buf_size + 1) >= 0) {
ref_name[buf_size] = '\0';
if (!h5str_append(out_str, ref_name))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
free(ref_name);
ref_name = NULL;
}
if (H5Rget_type(ref_vp) == H5R_ATTR) {
buf_size = H5Rget_attr_name(ref_vp, NULL, 0);
if (buf_size > 0) {
ref_name = (char *)malloc(sizeof(char) * (size_t)buf_size + 1);
if (H5Rget_attr_name(ref_vp, ref_name, (size_t)buf_size + 1) >= 0) {
ref_name[buf_size] = '\0';
if (!h5str_append(out_str, ref_name))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
free(ref_name);
ref_name = NULL;
}
}
ret_value = SUCCEED;
done:
if (ref_name)
free(ref_name);
return ret_value;
} /* h5str_sprint_reference */
int
h5str_old_region_dataset(JNIEnv *env, h5str_t *out_str, hid_t container, void *ref_buf, int expand_data)
{
H5S_sel_type region_type = H5S_SEL_ERROR;
hid_t region_obj = H5I_INVALID_HID;
hid_t region_sid = H5I_INVALID_HID;
int ret_value = FAIL;
if ((region_obj = H5Rdereference2(container, H5P_DEFAULT, H5R_DATASET_REGION, ref_buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((region_sid = H5Rget_region(container, H5R_DATASET_REGION, ref_buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (expand_data == 0)
if (h5str_sprint_old_reference(ENVONLY, out_str, region_obj, ref_buf) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((region_type = H5Sget_select_type(region_sid)) > H5S_SEL_ERROR) {
if (H5S_SEL_POINTS == region_type) {
if (h5str_dump_region_points(ENVONLY, out_str, region_sid, region_obj, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else if (H5S_SEL_HYPERSLABS == region_type) {
if (h5str_dump_region_blocks(ENVONLY, out_str, region_sid, region_obj, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
}
ret_value = SUCCEED;
done:
if (region_sid >= 0)
if (H5Sclose(region_sid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (region_obj >= 0)
if (H5Dclose(region_obj) < 0)
H5_LIBRARY_ERROR(ENVONLY);
return ret_value;
}
int
h5str_region_dataset(JNIEnv *env, h5str_t *out_str, H5R_ref_t *ref_vp, int expand_data)
{
hid_t new_obj_id = H5I_INVALID_HID;
hid_t new_obj_sid = H5I_INVALID_HID;
H5S_sel_type region_type;
int ret_value = FAIL;
if ((new_obj_id = H5Ropen_object(ref_vp, H5P_DEFAULT, H5P_DEFAULT)) < 0) {
ret_value = SUCCEED; /* An uncreated region is a valid state */
goto done;
}
if ((new_obj_sid = H5Ropen_region(ref_vp, H5P_DEFAULT, H5P_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (expand_data == 0)
if (h5str_sprint_reference(ENVONLY, out_str, ref_vp) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((region_type = H5Sget_select_type(new_obj_sid)) > H5S_SEL_ERROR) {
if (H5S_SEL_POINTS == region_type) {
if (h5str_dump_region_points(ENVONLY, out_str, new_obj_sid, new_obj_id, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else if (H5S_SEL_HYPERSLABS == region_type) {
if (h5str_dump_region_blocks(ENVONLY, out_str, new_obj_sid, new_obj_id, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
}
ret_value = SUCCEED;
done:
if (new_obj_sid >= 0)
if (H5Sclose(new_obj_sid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (new_obj_id >= 0)
if (H5Dclose(new_obj_id) < 0)
H5_LIBRARY_ERROR(ENVONLY);
return ret_value;
}
/*
* Prints the value of a data point into a string.
*
* Returns:
* SUCCESS: Total number of characters printed
* FAILURE: 0
*/
size_t
h5str_sprintf(JNIEnv *env, h5str_t *out_str, hid_t container, hid_t tid, void *in_buf, int expand_data)
{
unsigned char *ucptr = (unsigned char *)in_buf;
char fmt_llong[8], fmt_ullong[8];
H5T_class_t tclass = H5T_NO_CLASS;
size_t typeSize = 0;
H5T_sign_t nsign = H5T_SGN_ERROR;
hid_t mtid = H5I_INVALID_HID;
char *cptr = (char *)in_buf;
char *this_str = NULL;
int n;
size_t retVal = 0;
if (!out_str)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "h5str_sprintf: out_str is NULL");
if (!in_buf)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "h5str_sprintf: in_buf is NULL");
if (H5T_NO_CLASS == (tclass = H5Tget_class(tid)))
H5_LIBRARY_ERROR(ENVONLY);
if (!(typeSize = H5Tget_size(tid)))
H5_LIBRARY_ERROR(ENVONLY);
/* Build default formats for long long types */
if (!fmt_llong[0]) {
if (snprintf(fmt_llong, sizeof(fmt_llong), "%%lld") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
if (snprintf(fmt_ullong, sizeof(fmt_ullong), "%%llu") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
} /* end if */
switch (tclass) {
case H5T_FLOAT: {
switch (typeSize) {
case sizeof(float): {
float tmp_float = 0.0f;
memcpy(&tmp_float, cptr, sizeof(float));
size_t this_len = 25;
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%g", (double)tmp_float) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
}
case sizeof(double): {
double tmp_double = 0.0;
memcpy(&tmp_double, cptr, sizeof(double));
size_t this_len = 25;
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%g", tmp_double) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
}
#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE
case sizeof(long double): {
long double tmp_ldouble = 0.0L;
memcpy(&tmp_ldouble, cptr, sizeof(long double));
size_t this_len = 27;
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%Lg", tmp_ldouble) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
}
#endif
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY,
"h5str_sprintf: floating-point datatype size didn't match any of expected sizes");
break;
}
break;
}
case H5T_STRING: {
htri_t is_variable;
char *tmp_str;
typeSize = 0;
if ((is_variable = H5Tis_variable_str(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (is_variable) {
/* cp_vp is the pointer into the struct where a `char*' is stored. So we have
* to dereference the pointer to get the `char*' to pass to strlen(). */
tmp_str = *(char **)in_buf;
if (NULL != tmp_str)
typeSize = strlen(tmp_str);
}
else {
tmp_str = cptr;
}
/* Check for NULL pointer for string */
if (!tmp_str) {
if (NULL == (this_str = (char *)malloc(5)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
strncpy(this_str, "NULL", 5);
}
else {
if (typeSize > 0) {
if (NULL == (this_str = strdup(tmp_str)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
}
}
break;
}
case H5T_INTEGER: {
if (H5T_SGN_ERROR == (nsign = H5Tget_sign(tid)))
H5_LIBRARY_ERROR(ENVONLY);
switch (typeSize) {
case sizeof(char): {
unsigned char tmp_uchar = 0;
char tmp_char = 0;
size_t this_len = 7;
if (H5T_SGN_NONE == nsign) {
memcpy(&tmp_uchar, cptr, sizeof(unsigned char));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%hhu", tmp_uchar) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
memcpy(&tmp_char, cptr, sizeof(char));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%hhd", tmp_char) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
case sizeof(short): {
unsigned short tmp_ushort = 0;
short tmp_short = 0;
size_t this_len = 9;
if (H5T_SGN_NONE == nsign) {
memcpy(&tmp_ushort, cptr, sizeof(unsigned short));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%hu", tmp_ushort) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
memcpy(&tmp_short, cptr, sizeof(short));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%hd", tmp_short) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
case sizeof(int): {
unsigned int tmp_uint = 0;
int tmp_int = 0;
size_t this_len = 14;
if (H5T_SGN_NONE == nsign) {
memcpy(&tmp_uint, cptr, sizeof(unsigned int));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%u", tmp_uint) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
memcpy(&tmp_int, cptr, sizeof(int));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%d", tmp_int) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
#if H5_SIZEOF_LONG != H5_SIZEOF_INT
case sizeof(long): {
unsigned long tmp_ulong = 0;
long tmp_long = 0;
size_t this_len = 23;
if (H5T_SGN_NONE == nsign) {
memcpy(&tmp_ulong, cptr, sizeof(unsigned long));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%lu", tmp_ulong) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
memcpy(&tmp_long, cptr, sizeof(long));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, "%ld", tmp_long) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
#endif
#if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG
case sizeof(long long): {
unsigned long long tmp_ullong = 0;
long long tmp_llong = 0;
size_t this_len = 25;
if (H5T_SGN_NONE == nsign) {
memcpy(&tmp_ullong, cptr, sizeof(unsigned long long));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, fmt_ullong, tmp_ullong) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
memcpy(&tmp_llong, cptr, sizeof(long long));
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, this_len, fmt_llong, tmp_llong) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
#endif
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY, "h5str_sprintf: integer datatype size didn't match any of expected sizes");
break;
}
break;
}
case H5T_COMPOUND: {
unsigned i;
size_t offset;
if ((n = H5Tget_nmembers(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_append(out_str, H5_COMPOUND_BEGIN_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
for (i = 0; i < (unsigned)n; i++) {
offset = H5Tget_member_offset(tid, i);
if ((mtid = H5Tget_member_type(tid, i)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_sprintf(ENVONLY, out_str, container, mtid, &cptr[offset], expand_data))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((i + 1) < (unsigned)n)
if (!h5str_append(out_str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
}
if (!h5str_append(out_str, H5_COMPOUND_END_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
break;
}
case H5T_ENUM: {
char enum_name[1024];
if (H5Tenum_nameof(tid, cptr, enum_name, sizeof enum_name) >= 0) {
if (!h5str_append(out_str, enum_name))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
else {
size_t i;
size_t this_len = 4 * (typeSize + 1);
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if (1 == typeSize) {
if (snprintf(this_str, this_len, "%#02x", ucptr[0]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
for (i = 0; i < typeSize; i++)
if (snprintf(this_str, this_len, "%s%02x", i ? ":" : "", ucptr[i]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
}
break;
}
case H5T_REFERENCE: {
if (H5R_DSET_REG_REF_BUF_SIZE == typeSize) {
if (h5str_old_region_dataset(ENVONLY, out_str, container, cptr, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else if (H5R_OBJ_REF_BUF_SIZE == typeSize) {
H5O_info2_t oi;
hid_t obj = H5I_INVALID_HID;
char *obj_tok_str = NULL;
/*
* Object references -- show the type and OID of the referenced
* object.
*/
const size_t size = 64;
if (NULL == (this_str = (char *)malloc(size)))
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if ((obj = H5Rdereference2(container, H5P_DEFAULT, H5R_OBJECT, cptr)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Oget_info3(obj, &oi, H5O_INFO_ALL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Print object data and close object */
H5Otoken_to_str(obj, &oi.token, &obj_tok_str);
switch (oi.type) {
case H5O_TYPE_GROUP:
if (snprintf(this_str, size, "%s %s", H5_TOOLS_GROUP, obj_tok_str) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_DATASET:
if (snprintf(this_str, size, "%s %s", H5_TOOLS_DATASET, obj_tok_str) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_NAMED_DATATYPE:
if (snprintf(this_str, size, "%s %s", H5_TOOLS_DATATYPE, obj_tok_str) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_MAP:
if (snprintf(this_str, size, "%s %s", H5_TOOLS_MAP, obj_tok_str) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
if (snprintf(this_str, size, "%u-%s", (unsigned)oi.type, obj_tok_str) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
break;
}
if (obj_tok_str) {
H5free_memory(obj_tok_str);
obj_tok_str = NULL;
}
if (H5Oclose(obj) < 0)
H5_LIBRARY_ERROR(ENVONLY);
obj = H5I_INVALID_HID;
}
else {
/* H5T_STD_REF */
hid_t new_obj_id = H5I_INVALID_HID;
H5O_type_t obj_type = -1; /* Object type */
H5R_type_t ref_type; /* Reference type */
H5R_ref_t loc_ref;
memcpy(&loc_ref, cptr, sizeof(H5R_ref_t));
ref_type = H5Rget_type(&loc_ref);
if (!h5str_is_zero(&loc_ref, H5Tget_size(H5T_STD_REF))) {
switch (ref_type) {
case H5R_OBJECT1:
if (H5Rget_obj_type3(&loc_ref, H5P_DEFAULT, &obj_type) >= 0) {
switch (obj_type) {
case H5O_TYPE_DATASET:
if (h5str_region_dataset(ENVONLY, out_str, &loc_ref, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
case H5O_TYPE_GROUP:
case H5O_TYPE_NAMED_DATATYPE:
case H5O_TYPE_MAP:
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default: {
/* Object references -- show the type and
* OID of the referenced object. */
H5O_info2_t oi;
char *obj_tok_str = NULL;
if ((new_obj_id =
H5Ropen_object(&loc_ref, H5P_DEFAULT, H5P_DEFAULT)) >= 0) {
H5Oget_info3(new_obj_id, &oi, H5O_INFO_BASIC);
H5Otoken_to_str(new_obj_id, &oi.token, &obj_tok_str);
if (H5Dclose(new_obj_id) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
else
H5_LIBRARY_ERROR(ENVONLY);
size_t this_len = 14;
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(
ENVONLY, "h5str_sprintf: failed to allocate string buffer");
switch (oi.type) {
case H5O_TYPE_GROUP:
if (snprintf(this_str, this_len, "%s ", H5_TOOLS_GROUP) < 0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_DATASET:
if (snprintf(this_str, this_len, "%s ", H5_TOOLS_DATASET) < 0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_NAMED_DATATYPE:
if (snprintf(this_str, this_len, "%s ", H5_TOOLS_DATATYPE) <
0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_MAP:
if (snprintf(this_str, this_len, "%s ", H5_TOOLS_MAP) < 0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
break;
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
if (snprintf(this_str, this_len, "%u-", (unsigned)oi.type) <
0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
break;
} /* end switch */
if (!h5str_append(out_str, this_str))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
free(this_str);
this_str = NULL;
/* Print OID */
{
char *token_str;
H5Otoken_to_str(tid, &oi.token, &token_str);
size_t that_len = 64 + strlen(token_str) + 1;
if (NULL == (this_str = malloc(that_len)))
H5_OUT_OF_MEMORY_ERROR(
ENVONLY,
"h5str_sprintf: failed to allocate string buffer");
if (snprintf(this_str, that_len, "%lu:%s", oi.fileno, token_str) <
0)
H5_JNI_FATAL_ERROR(ENVONLY,
"h5str_sprintf: snprintf failure");
H5free_memory(token_str);
}
} break;
} /* end switch */
}
else
H5_LIBRARY_ERROR(ENVONLY);
break;
case H5R_DATASET_REGION1:
if (h5str_region_dataset(ENVONLY, out_str, &loc_ref, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
case H5R_OBJECT2:
if (H5Rget_obj_type3(&loc_ref, H5P_DEFAULT, &obj_type) >= 0) {
switch (obj_type) {
case H5O_TYPE_GROUP:
break;
case H5O_TYPE_DATASET:
if (h5str_region_dataset(ENVONLY, out_str, &loc_ref, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
case H5O_TYPE_NAMED_DATATYPE:
break;
case H5O_TYPE_MAP:
case H5O_TYPE_UNKNOWN:
case H5O_TYPE_NTYPES:
default:
break;
} /* end switch */
}
else
H5_ASSERTION_ERROR(ENVONLY, "h5str_sprintf: H5R_OBJECT2 failed");
break;
case H5R_DATASET_REGION2:
if (h5str_region_dataset(ENVONLY, out_str, &loc_ref, expand_data) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
case H5R_ATTR:
if ((new_obj_id = H5Ropen_attr(&loc_ref, H5P_DEFAULT, H5P_DEFAULT)) >= 0) {
if (h5str_dump_region_attribute(ENVONLY, out_str, new_obj_id) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (H5Aclose(new_obj_id) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
break;
case H5R_BADTYPE:
case H5R_MAXTYPE:
default:
break;
} /* end switch */
}
if (H5Rdestroy(&loc_ref) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
break;
}
case H5T_ARRAY: {
hsize_t dims[H5S_MAX_RANK], i, total_elmts;
size_t baseSize;
int rank = 0;
if (!h5str_append(out_str, H5_ARRAY_BEGIN_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
if ((rank = H5Tget_array_ndims(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tget_array_dims2(tid, dims) < 0)
H5_LIBRARY_ERROR(ENVONLY);
for (i = 0, total_elmts = 1; i < (hsize_t)rank; i++)
total_elmts *= dims[i];
for (i = 0; i < total_elmts; i++) {
if (!h5str_sprintf(ENVONLY, out_str, container, mtid, &(cptr[i * baseSize]), expand_data))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((i + 1) < total_elmts)
if (!h5str_append(out_str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
if (!h5str_append(out_str, H5_ARRAY_END_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
break;
}
case H5T_VLEN: {
unsigned int i;
size_t baseSize;
hvl_t *vl_buf = (hvl_t *)in_buf;
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_append(out_str, H5_VLEN_BEGIN_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
for (i = 0; i < (unsigned)vl_buf->len; i++) {
if (!h5str_sprintf(ENVONLY, out_str, container, mtid, &(((char *)vl_buf->p)[i * baseSize]),
expand_data))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((i + 1) < (unsigned)vl_buf->len)
if (!h5str_append(out_str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
if (!h5str_append(out_str, H5_VLEN_END_INDICATOR))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
break;
}
case H5T_COMPLEX: {
h5str_t real_part, imag_part;
size_t baseSize;
h5str_new(&real_part, 128);
h5str_new(&imag_part, 128);
/* Get the base datatype for the complex number type */
if ((mtid = H5Tget_super(tid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(baseSize = H5Tget_size(mtid)))
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_sprintf(ENVONLY, &real_part, container, mtid, cptr, expand_data))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (!h5str_sprintf(ENVONLY, &imag_part, container, mtid, cptr + baseSize, expand_data))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (!h5str_append(out_str, real_part.s))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (NULL == strstr(imag_part.s, "-"))
if (!h5str_append(out_str, "+"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (!h5str_append(out_str, imag_part.s))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (!h5str_append(out_str, "i"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (H5Tclose(mtid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
mtid = H5I_INVALID_HID;
h5str_free(&real_part);
h5str_free(&imag_part);
break;
}
case H5T_NO_CLASS:
case H5T_NCLASSES: {
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_sprintf: invalid datatype class");
break;
}
case H5T_TIME:
case H5T_BITFIELD:
case H5T_OPAQUE:
default: {
size_t i;
/* All other types get printed as hexadecimal */
size_t this_len = 4 * (typeSize + 1);
if (NULL == (this_str = (char *)malloc(this_len)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_sprintf: failed to allocate string buffer");
if (1 == typeSize) {
if (snprintf(this_str, this_len, "%#02x", ucptr[0]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
else {
for (i = 0; i < typeSize; i++)
if (snprintf(this_str, this_len, "%s%02x", i ? ":" : "", ucptr[i]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_sprintf: snprintf failure");
}
break;
}
}
if (this_str) {
if (!h5str_append(out_str, this_str))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
free(this_str);
this_str = NULL;
} /* end if */
retVal = strlen(out_str->s);
done:
if (mtid >= 0)
H5Tclose(mtid);
return retVal;
} /* end h5str_sprintf */
/*-------------------------------------------------------------------------
* Purpose: Print the data values from a dataset referenced by region blocks.
*
* Description:
* This is a special case subfunction to print the data in a region reference of type blocks.
*
* Return:
* The function returns FAIL if there was an error, otherwise SUCCEED
*-------------------------------------------------------------------------
*/
static int
h5str_print_region_data_blocks(JNIEnv *env, hid_t region_id, h5str_t *str, int ndims, hid_t type_id,
hssize_t nblocks, hsize_t *ptdata)
{
unsigned indx;
hsize_t *dims1 = NULL;
hsize_t *start = NULL;
hsize_t *count = NULL;
hsize_t blkndx;
hsize_t total_size[H5S_MAX_RANK];
hsize_t numelem;
hsize_t numindex;
size_t jndx;
size_t type_size;
hid_t mem_space = H5I_INVALID_HID;
hid_t sid1 = H5I_INVALID_HID;
void *region_buf = NULL;
int ret_value = FAIL;
if (ndims < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_print_region_data_blocks: ndims < 0");
if (nblocks < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_print_region_data_blocks: nblocks < 0");
/* Get the dataspace of the dataset */
if ((sid1 = H5Dget_space(region_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Allocate space for the dimension array */
if (NULL == (dims1 = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_print_region_data_blocks: failed to allocate dimension array buffer");
/* Find the dimensions of each data space from the block coordinates */
for (jndx = 0, numelem = 1; jndx < (size_t)ndims; jndx++) {
dims1[jndx] = ptdata[jndx + (size_t)ndims] - ptdata[jndx] + 1;
numelem = dims1[jndx] * numelem;
} /* end for */
/* Create dataspace for reading buffer */
if ((mem_space = H5Screate_simple(ndims, dims1, NULL)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(type_size = H5Tget_size(type_id)))
H5_LIBRARY_ERROR(ENVONLY);
if (NULL == (region_buf = malloc(type_size * (size_t)numelem)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_print_region_data_blocks: failed to allocate region buffer");
/* Select (x , x , ..., x ) x (y , y , ..., y ) hyperslab for reading memory dataset */
/* 1 2 n 1 2 n */
if (NULL == (start = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_print_region_data_blocks: failed to allocate hyperslab start buffer");
if (NULL == (count = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_print_region_data_blocks: failed to allocate hyperslab count buffer");
for (blkndx = 0; blkndx < (hsize_t)nblocks; blkndx++) {
for (indx = 0; indx < (unsigned)ndims; indx++) {
start[indx] = ptdata[indx + blkndx * (hsize_t)ndims * 2];
count[indx] = dims1[indx];
} /* end for */
if (H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Dread(region_id, type_id, mem_space, sid1, H5P_DEFAULT, region_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
for (numindex = 0; numindex < numelem; numindex++) {
if (!h5str_sprintf(ENVONLY, str, region_id, type_id, ((char *)region_buf + numindex * type_size),
1))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (numindex + 1 < numelem)
if (!h5str_append(str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
} /* end for (jndx = 0; jndx < numelem; jndx++, region_elmtno++, ctx.cur_elmt++) */
} /* end for (blkndx = 0; blkndx < nblocks; blkndx++) */
ret_value = SUCCEED;
done:
if (count)
free(count);
if (start)
free(start);
if (region_buf)
free(region_buf);
if (mem_space >= 0)
H5Sclose(mem_space);
if (dims1)
free(dims1);
if (sid1 >= 0)
H5Sclose(sid1);
return ret_value;
} /* end h5str_print_region_data_blocks */
int
h5str_dump_region_blocks(JNIEnv *env, h5str_t *str, hid_t region_space, hid_t region_id, int expand_data)
{
hssize_t nblocks;
hsize_t alloc_size;
hsize_t *ptdata = NULL;
hid_t dtype = H5I_INVALID_HID;
hid_t type_id = H5I_INVALID_HID;
int ndims = -1;
int ret_value = FAIL;
int i;
char tmp_str[256];
/*
* This function fails if the region does not have blocks.
*/
H5E_BEGIN_TRY
{
nblocks = H5Sget_select_hyper_nblocks(region_space);
}
H5E_END_TRY
if (nblocks <= 0) {
ret_value = SUCCEED;
goto done;
}
if ((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Print block information */
alloc_size = (hsize_t)nblocks * (hsize_t)ndims * 2 * (hsize_t)sizeof(ptdata[0]);
if (NULL == (ptdata = (hsize_t *)malloc((size_t)alloc_size)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_region_blocks: failed to allocate region block buffer");
if (H5Sget_select_hyper_blocklist(region_space, (hsize_t)0, (hsize_t)nblocks, ptdata) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (expand_data) {
if ((dtype = H5Dget_type(region_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (h5str_print_region_data_blocks(ENVONLY, region_id, str, ndims, type_id, nblocks, ptdata) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (!h5str_append(str, " REGION_TYPE BLOCK"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (!h5str_append(str, " {"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
for (i = 0; i < nblocks; i++) {
int j;
if (!h5str_append(str, " "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
/* Start coordinates and opposite corner */
for (j = 0; j < ndims; j++) {
tmp_str[0] = '\0';
if (snprintf(tmp_str, sizeof(tmp_str), "%s%lu", j ? "," : "(",
(unsigned long)ptdata[i * 2 * ndims + j]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_region_blocks: snprintf failure");
if (!h5str_append(str, tmp_str))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
for (j = 0; j < ndims; j++) {
tmp_str[0] = '\0';
if (snprintf(tmp_str, sizeof(tmp_str), "%s%lu", j ? "," : ")-(",
(unsigned long)ptdata[i * 2 * ndims + j + ndims]) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_region_blocks: snprintf failure");
if (!h5str_append(str, tmp_str))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
if (!h5str_append(str, ") "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
tmp_str[0] = '\0';
}
if (!h5str_append(str, " }"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
ret_value = SUCCEED;
done:
if (type_id >= 0)
H5Tclose(type_id);
if (dtype >= 0)
H5Tclose(dtype);
if (ptdata)
free(ptdata);
return ret_value;
} /* end h5str_dump_region_blocks */
/*-------------------------------------------------------------------------
* Purpose: Print the data values from a dataset referenced by region points.
*
* Description:
* This is a special case subfunction to print the data in a region reference of type points.
*
* Return:
* The function returns FAIL on error, otherwise SUCCEED
*-------------------------------------------------------------------------
*/
static int
h5str_print_region_data_points(JNIEnv *env, hid_t region_space, hid_t region_id, h5str_t *str, int ndims,
hid_t type_id, hssize_t npoints, hsize_t *ptdata)
{
hsize_t *dims1 = NULL;
hsize_t total_size[H5S_MAX_RANK];
size_t jndx;
size_t type_size;
hid_t mem_space = H5I_INVALID_HID;
void *region_buf = NULL;
int ret_value = FAIL;
UNUSED(ptdata);
if (npoints < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_print_region_data_points: npoints < 0");
/* Allocate space for the dimension array */
if (NULL == (dims1 = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_print_region_data_points: failed to allocate dimension array buffer");
dims1[0] = (hsize_t)npoints;
/* Create dataspace for reading buffer */
if ((mem_space = H5Screate_simple(1, dims1, NULL)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(type_size = H5Tget_size(type_id)))
H5_LIBRARY_ERROR(ENVONLY);
if (NULL == (region_buf = malloc(type_size * (size_t)npoints)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_print_region_data_points: failed to allocate region buffer");
if (H5Dread(region_id, type_id, mem_space, region_space, H5P_DEFAULT, region_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
for (jndx = 0; jndx < (size_t)npoints; jndx++) {
if (H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!h5str_sprintf(ENVONLY, str, region_id, type_id, ((char *)region_buf + jndx * type_size), 1))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (jndx + 1 < (size_t)npoints)
if (!h5str_append(str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
} /* end for (jndx = 0; jndx < npoints; jndx++, elmtno++) */
ret_value = SUCCEED;
done:
if (region_buf)
free(region_buf);
if (mem_space >= 0)
H5Sclose(mem_space);
if (dims1)
free(dims1);
return ret_value;
} /* end h5str_print_region_data_points */
int
h5str_dump_region_points(JNIEnv *env, h5str_t *str, hid_t region_space, hid_t region_id, int expand_data)
{
hsize_t alloc_size;
hssize_t npoints = -1;
hsize_t *ptdata = NULL;
hid_t dtype = H5I_INVALID_HID;
hid_t type_id = H5I_INVALID_HID;
int ndims = -1;
int ret_value = FAIL;
int i;
char tmp_str[256];
/*
* This function fails if the region does not have points.
*/
H5E_BEGIN_TRY
{
npoints = H5Sget_select_elem_npoints(region_space);
}
H5E_END_TRY
if (npoints <= 0) {
ret_value = SUCCEED;
goto done;
}
if ((ndims = H5Sget_simple_extent_ndims(region_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Print point information */
alloc_size = (hsize_t)npoints * (hsize_t)ndims * (hsize_t)sizeof(ptdata[0]);
if (NULL == (ptdata = (hsize_t *)malloc((size_t)alloc_size)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"h5str_dump_region_points: failed to allocate region point data buffer");
if (H5Sget_select_elem_pointlist(region_space, (hsize_t)0, (hsize_t)npoints, ptdata) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (expand_data) {
if ((dtype = H5Dget_type(region_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (h5str_print_region_data_points(ENVONLY, region_space, region_id, str, ndims, type_id, npoints,
ptdata) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (!h5str_append(str, " REGION_TYPE POINT"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
if (!h5str_append(str, " {"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
for (i = 0; i < npoints; i++) {
int j;
if (!h5str_append(str, " "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
for (j = 0; j < ndims; j++) {
tmp_str[0] = '\0';
if (snprintf(tmp_str, sizeof(tmp_str), "%s%lu", j ? "," : "(",
(unsigned long)(ptdata[i * ndims + j])) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_region_points: snprintf failure");
if (!h5str_append(str, tmp_str))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
} /* end for (j = 0; j < ndims; j++) */
if (!h5str_append(str, ") "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
} /* end for (i = 0; i < npoints; i++) */
if (!h5str_append(str, " }"))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
ret_value = SUCCEED;
done:
if (type_id >= 0)
H5Tclose(type_id);
if (dtype >= 0)
H5Tclose(dtype);
if (ptdata)
free(ptdata);
return ret_value;
} /* end h5str_dump_region_points */
static int
h5str_is_zero(const void *_mem, size_t size)
{
const unsigned char *mem = (const unsigned char *)_mem;
while (size-- > 0)
if (mem[size])
return 0;
return 1;
} /* end h5str_is_zero */
/*-------------------------------------------------------------------------
* Function: h5str_detect_vlen
*
* Purpose: Recursive check for any variable length data in given type.
*
* Return:
* 1 : type contains any variable length data
* 0 : type doesn't contain any variable length data
* Negative value: error occurred
*-------------------------------------------------------------------------
*/
htri_t
h5str_detect_vlen(hid_t tid)
{
htri_t ret = FAIL;
/* Recursively detect any vlen data values in type (compound, array ...) */
ret = H5Tdetect_class(tid, H5T_VLEN);
if ((ret == 1) || (ret < 0))
goto done;
/* Recursively detect any vlen string in type (compound, array ...) */
ret = h5str_detect_vlen_str(tid);
if ((ret == 1) || (ret < 0))
goto done;
done:
return ret;
} /* end h5str_detect_vlen */
/*-------------------------------------------------------------------------
* Function: h5str_detect_vlen_str
*
* Purpose: Recursive check for variable length string of a datatype.
*
* Return:
* true : type contains any variable length string
* false : type doesn't contain any variable length string
* Negative value: error occur
*
*-------------------------------------------------------------------------
*/
static htri_t
h5str_detect_vlen_str(hid_t tid)
{
H5T_class_t tclass = H5T_NO_CLASS;
htri_t ret = 0;
ret = H5Tis_variable_str(tid);
if ((ret == 1) || (ret < 0))
goto done;
tclass = H5Tget_class(tid);
if (tclass == H5T_ARRAY || tclass == H5T_VLEN) {
hid_t btid = H5Tget_super(tid);
if (btid < 0) {
ret = (htri_t)btid;
goto done;
} /* end if */
ret = h5str_detect_vlen_str(btid);
H5Tclose(btid);
if ((ret == 1) || (ret < 0)) {
goto done;
} /* end if */
} /* end if */
else if (tclass == H5T_COMPOUND) {
unsigned i = 0;
int n = H5Tget_nmembers(tid);
if (n < 0)
goto done;
for (i = 0; i < (unsigned)n; i++) {
hid_t mtid = H5Tget_member_type(tid, i);
ret = h5str_detect_vlen_str(mtid);
if ((ret == 1) || (ret < 0)) {
H5Tclose(mtid);
goto done;
}
H5Tclose(mtid);
} /* end for */
} /* end else */
done:
return ret;
} /* end h5str_detect_vlen_str */
/*-------------------------------------------------------------------------
* Function: h5str_get_native_type
*
* Purpose: Wrapper around H5Tget_native_type() to work around
* Problems with bitfields.
*
* Return: Success: datatype ID
* Failure: FAIL
*-------------------------------------------------------------------------
*/
static hid_t
h5str_get_native_type(hid_t type)
{
H5T_class_t type_class;
hid_t p_type = H5I_INVALID_HID;
if ((type_class = H5Tget_class(type)) < 0)
goto done;
if (type_class == H5T_BITFIELD)
p_type = H5Tcopy(type);
else
p_type = H5Tget_native_type(type, H5T_DIR_DEFAULT);
done:
return (p_type);
} /* end h5str_get_native_type */
/*-------------------------------------------------------------------------
* Function: h5str_get_little_endian_type
*
* Purpose: Get a little endian type from a file type
*
* Return: Success: datatype ID
* Failure: FAIL
*-------------------------------------------------------------------------
*/
static hid_t
h5str_get_little_endian_type(hid_t tid)
{
H5T_class_t type_class;
H5T_sign_t sign;
size_t size;
hid_t p_type = H5I_INVALID_HID;
if ((type_class = H5Tget_class(tid)) < 0)
goto done;
if (!(size = H5Tget_size(tid)))
goto done;
if ((sign = H5Tget_sign(tid)) < 0)
goto done;
switch (type_class) {
case H5T_INTEGER: {
if (size == 1 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I8LE);
else if (size == 2 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I16LE);
else if (size == 4 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I32LE);
else if (size == 8 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I64LE);
else if (size == 1 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U8LE);
else if (size == 2 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U16LE);
else if (size == 4 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U32LE);
else if (size == 8 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U64LE);
break;
}
case H5T_FLOAT: {
if (size == 1) {
if (true == H5Tequal(tid, H5T_FLOAT_F8E4M3))
p_type = H5Tcopy(H5T_FLOAT_F8E4M3);
else if (true == H5Tequal(tid, H5T_FLOAT_F8E5M2))
p_type = H5Tcopy(H5T_FLOAT_F8E5M2);
else if (true == H5Tequal(tid, H5T_FLOAT_F6E2M3))
p_type = H5Tcopy(H5T_FLOAT_F6E2M3);
else if (true == H5Tequal(tid, H5T_FLOAT_F6E3M2))
p_type = H5Tcopy(H5T_FLOAT_F6E3M2);
else if (true == H5Tequal(tid, H5T_FLOAT_F4E2M1))
p_type = H5Tcopy(H5T_FLOAT_F4E2M1);
}
else if (size == 2) {
if (true == H5Tequal(tid, H5T_IEEE_F16LE) || true == H5Tequal(tid, H5T_IEEE_F16BE))
p_type = H5Tcopy(H5T_IEEE_F16LE);
else if (true == H5Tequal(tid, H5T_FLOAT_BFLOAT16LE) ||
true == H5Tequal(tid, H5T_FLOAT_BFLOAT16BE))
p_type = H5Tcopy(H5T_FLOAT_BFLOAT16LE);
}
else if (size == 4)
p_type = H5Tcopy(H5T_IEEE_F32LE);
else if (size == 8)
p_type = H5Tcopy(H5T_IEEE_F64LE);
break;
}
case H5T_BITFIELD: {
if (size == 1)
p_type = H5Tcopy(H5T_STD_B8LE);
else if (size == 2)
p_type = H5Tcopy(H5T_STD_B16LE);
else if (size == 4)
p_type = H5Tcopy(H5T_STD_B32LE);
else if (size == 8)
p_type = H5Tcopy(H5T_STD_B64LE);
break;
}
case H5T_COMPLEX: {
if (size == 4)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F16LE);
else if (size == 8)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F32LE);
else if (size == 16)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F64LE);
break;
}
case H5T_NO_CLASS:
case H5T_NCLASSES: {
goto done;
break;
}
case H5T_TIME:
case H5T_OPAQUE:
case H5T_STRING:
case H5T_COMPOUND:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
case H5T_ARRAY:
break;
default:
break;
}
done:
return (p_type);
} /* end h5str_get_little_endian_type */
/*-------------------------------------------------------------------------
* Function: h5str_get_big_endian_type
*
* Purpose: Get a big endian type from a file type
*
* Return: Success: datatype ID
* Failure: FAIL
*-------------------------------------------------------------------------
*/
static hid_t
h5str_get_big_endian_type(hid_t tid)
{
H5T_class_t type_class;
H5T_sign_t sign;
size_t size;
hid_t p_type = H5I_INVALID_HID;
if ((type_class = H5Tget_class(tid)) < 0)
goto done;
if (!(size = H5Tget_size(tid)))
goto done;
if ((sign = H5Tget_sign(tid)) < 0)
goto done;
switch (type_class) {
case H5T_INTEGER: {
if (size == 1 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I8BE);
else if (size == 2 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I16BE);
else if (size == 4 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I32BE);
else if (size == 8 && sign == H5T_SGN_2)
p_type = H5Tcopy(H5T_STD_I64BE);
else if (size == 1 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U8BE);
else if (size == 2 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U16BE);
else if (size == 4 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U32BE);
else if (size == 8 && sign == H5T_SGN_NONE)
p_type = H5Tcopy(H5T_STD_U64BE);
break;
}
case H5T_FLOAT: {
if (size == 1) {
if (true == H5Tequal(tid, H5T_FLOAT_F8E4M3)) {
p_type = H5Tcopy(H5T_FLOAT_F8E4M3);
/* Though not very useful, set order to BE as expected */
H5Tset_order(p_type, H5T_ORDER_BE);
}
else if (true == H5Tequal(tid, H5T_FLOAT_F8E5M2)) {
p_type = H5Tcopy(H5T_FLOAT_F8E5M2);
/* Though not very useful, set order to BE as expected */
H5Tset_order(p_type, H5T_ORDER_BE);
}
else if (true == H5Tequal(tid, H5T_FLOAT_F6E2M3)) {
p_type = H5Tcopy(H5T_FLOAT_F6E2M3);
/* Though not very useful, set order to BE as expected */
H5Tset_order(p_type, H5T_ORDER_BE);
}
else if (true == H5Tequal(tid, H5T_FLOAT_F6E3M2)) {
p_type = H5Tcopy(H5T_FLOAT_F6E3M2);
/* Though not very useful, set order to BE as expected */
H5Tset_order(p_type, H5T_ORDER_BE);
}
else if (true == H5Tequal(tid, H5T_FLOAT_F4E2M1)) {
p_type = H5Tcopy(H5T_FLOAT_F4E2M1);
/* Though not very useful, set order to BE as expected */
H5Tset_order(p_type, H5T_ORDER_BE);
}
}
else if (size == 2) {
if (true == H5Tequal(tid, H5T_IEEE_F16LE) || true == H5Tequal(tid, H5T_IEEE_F16BE))
p_type = H5Tcopy(H5T_IEEE_F16BE);
else if (true == H5Tequal(tid, H5T_FLOAT_BFLOAT16LE) ||
true == H5Tequal(tid, H5T_FLOAT_BFLOAT16BE))
p_type = H5Tcopy(H5T_FLOAT_BFLOAT16BE);
}
else if (size == 4)
p_type = H5Tcopy(H5T_IEEE_F32BE);
else if (size == 8)
p_type = H5Tcopy(H5T_IEEE_F64BE);
break;
}
case H5T_BITFIELD: {
if (size == 1)
p_type = H5Tcopy(H5T_STD_B8BE);
else if (size == 2)
p_type = H5Tcopy(H5T_STD_B16BE);
else if (size == 4)
p_type = H5Tcopy(H5T_STD_B32BE);
else if (size == 8)
p_type = H5Tcopy(H5T_STD_B64BE);
break;
}
case H5T_COMPLEX: {
if (size == 4)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F16BE);
else if (size == 8)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F32BE);
else if (size == 16)
p_type = H5Tcopy(H5T_COMPLEX_IEEE_F64BE);
break;
}
case H5T_NO_CLASS:
case H5T_NCLASSES: {
goto done;
break;
}
case H5T_TIME:
case H5T_OPAQUE:
case H5T_STRING:
case H5T_COMPOUND:
case H5T_REFERENCE:
case H5T_ENUM:
case H5T_VLEN:
case H5T_ARRAY:
break;
default:
break;
}
done:
return (p_type);
} /* end h5str_get_big_endian_type */
/*-------------------------------------------------------------------------
* Function: render_bin_output
*
* Purpose: Write one element of memory buffer to a binary file stream
*
* Return: Success: SUCCEED
* Failure: FAIL
*-------------------------------------------------------------------------
*/
static int
h5str_render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem, hsize_t block_nelmts)
{
unsigned char *mem = (unsigned char *)_mem;
H5T_class_t type_class;
hsize_t block_index;
size_t size; /* datum size */
int ret_value = 0;
if (!(size = H5Tget_size(tid))) {
ret_value = FAIL;
goto done;
}
if ((type_class = H5Tget_class(tid)) < 0) {
ret_value = FAIL;
goto done;
}
switch (type_class) {
case H5T_INTEGER:
case H5T_FLOAT:
case H5T_ENUM: {
block_index = block_nelmts * size;
while (block_index > 0) {
size_t bytes_in = 0; /* # of bytes to write */
size_t bytes_wrote = 0; /* # of bytes written */
if (block_index > sizeof(size_t))
bytes_in = sizeof(size_t);
else
bytes_in = (size_t)block_index;
bytes_wrote = fwrite(mem, 1, bytes_in, stream);
if (bytes_wrote != bytes_in || (0 == bytes_wrote && ferror(stream))) {
ret_value = FAIL;
break;
}
block_index -= (hsize_t)bytes_wrote;
mem = mem + bytes_wrote;
}
break;
}
case H5T_STRING: {
unsigned int i;
H5T_str_t pad;
char *s = NULL;
unsigned char tempuchar;
if ((pad = H5Tget_strpad(tid)) < 0) {
ret_value = FAIL;
goto done;
}
for (block_index = 0; block_index < block_nelmts; block_index++) {
mem = ((unsigned char *)_mem) + block_index * size;
if (H5Tis_variable_str(tid)) {
s = *(char **)((void *)mem);
if (s != NULL)
size = strlen(s);
}
else {
s = (char *)mem;
}
for (i = 0; i < size && (s[i] || pad != H5T_STR_NULLTERM); i++) {
memcpy(&tempuchar, &s[i], sizeof(unsigned char));
if (1 != fwrite(&tempuchar, sizeof(unsigned char), 1, stream)) {
ret_value = FAIL;
break;
}
} /* i */
if (ret_value < 0)
break;
} /* for (block_index = 0; block_index < block_nelmts; block_index++) */
break;
}
case H5T_COMPOUND: {
unsigned j;
size_t offset;
hid_t memb = H5I_INVALID_HID;
int nmembs;
if ((nmembs = H5Tget_nmembers(tid)) < 0) {
ret_value = FAIL;
goto done;
}
for (block_index = 0; block_index < block_nelmts; block_index++) {
mem = ((unsigned char *)_mem) + block_index * size;
for (j = 0; j < (unsigned)nmembs; j++) {
offset = H5Tget_member_offset(tid, j);
memb = H5Tget_member_type(tid, j);
if (h5str_render_bin_output(stream, container, memb, mem + offset, 1) < 0) {
H5Tclose(memb);
ret_value = FAIL;
break;
}
H5Tclose(memb);
}
if (ret_value < 0)
break;
}
break;
}
case H5T_ARRAY: {
hsize_t dims[H5S_MAX_RANK], temp_nelmts, nelmts;
hid_t memb;
int k, ndims;
/* Get the array's base datatype for each element */
if ((memb = H5Tget_super(tid)) < 0) {
ret_value = FAIL;
goto done;
}
if ((ndims = H5Tget_array_ndims(tid)) < 0) {
ret_value = FAIL;
goto done;
}
if (H5Tget_array_dims2(tid, dims) < 0) {
ret_value = FAIL;
goto done;
}
/* Calculate the number of array elements */
for (k = 0, nelmts = 1; k < ndims; k++) {
temp_nelmts = nelmts;
temp_nelmts *= dims[k];
nelmts = (size_t)temp_nelmts;
}
for (block_index = 0; block_index < block_nelmts; block_index++) {
mem = ((unsigned char *)_mem) + block_index * size;
/* dump the array element */
if (h5str_render_bin_output(stream, container, memb, mem, nelmts) < 0) {
ret_value = FAIL;
break;
}
}
H5Tclose(memb);
break;
}
case H5T_VLEN: {
hsize_t nelmts;
hid_t memb;
/* Get the VL sequences's base datatype for each element */
if ((memb = H5Tget_super(tid)) < 0) {
ret_value = FAIL;
goto done;
}
for (block_index = 0; block_index < block_nelmts; block_index++) {
hvl_t vl_elem;
memcpy(&vl_elem, ((unsigned char *)_mem) + block_index * size, sizeof(hvl_t));
/* Get the number of sequence elements */
nelmts = vl_elem.len;
/* dump the array element */
if (h5str_render_bin_output(stream, container, memb, ((char *)(vl_elem.p)), nelmts) < 0) {
ret_value = FAIL;
break;
}
}
H5Tclose(memb);
break;
}
case H5T_REFERENCE: {
hid_t region_id = H5I_INVALID_HID;
hid_t region_space = H5I_INVALID_HID;
H5S_sel_type region_type;
/* Region data */
for (block_index = 0; block_index < block_nelmts; block_index++) {
H5R_ref_t loc_ref;
memcpy(&loc_ref, ((unsigned char *)_mem) + block_index * size, sizeof(H5R_ref_t));
if ((region_id = H5Ropen_object(&loc_ref, H5P_DEFAULT, H5P_DEFAULT)) < 0)
continue;
if ((region_space = H5Ropen_region(&loc_ref, H5P_DEFAULT, H5P_DEFAULT)) >= 0) {
if (!h5str_is_zero(&loc_ref, H5Tget_size(H5T_STD_REF))) {
region_type = H5Sget_select_type(region_space);
if (region_type == H5S_SEL_POINTS)
ret_value =
render_bin_output_region_points(stream, region_space, region_id, container);
else if (region_type == H5S_SEL_HYPERSLABS)
ret_value =
render_bin_output_region_blocks(stream, region_space, region_id, container);
}
H5Sclose(region_space);
} /* end if (region_space >= 0) */
H5Dclose(region_id);
if (ret_value < 0)
break;
}
break;
}
case H5T_COMPLEX: {
hid_t memb = H5I_INVALID_HID;
if ((memb = H5Tget_super(tid)) < 0) {
ret_value = FAIL;
goto done;
}
for (block_index = 0; block_index < block_nelmts; block_index++) {
mem = ((unsigned char *)_mem) + block_index * size;
/* dump the complex number element */
if (h5str_render_bin_output(stream, container, memb, mem, 2) < 0) {
ret_value = FAIL;
break;
}
}
if (H5Tclose(memb) < 0) {
ret_value = FAIL;
goto done;
}
break;
}
case H5T_NO_CLASS:
case H5T_NCLASSES: {
ret_value = FAIL;
goto done;
break;
}
case H5T_TIME:
case H5T_BITFIELD:
case H5T_OPAQUE:
default:
for (block_index = 0; block_index < block_nelmts; block_index++) {
mem = ((unsigned char *)_mem) + block_index * size;
if (size != fwrite(mem, sizeof(char), size, stream)) {
ret_value = FAIL;
break;
}
}
break;
}
done:
return ret_value;
} /* end h5str_render_bin_output */
/*-------------------------------------------------------------------------
* Purpose: Print the data values from a dataset referenced by region blocks.
*
* Description:
* This is a special case subfunction to print the data in a region reference of type blocks.
*
* Return:
* The function returns FAIL if there was an error, otherwise SUCCEED
*
*-------------------------------------------------------------------------
*/
static int
render_bin_output_region_data_blocks(FILE *stream, hid_t region_id, hid_t container, int ndims, hid_t type_id,
hssize_t nblocks, hsize_t *ptdata)
{
hsize_t *dims1 = NULL;
hsize_t *start = NULL;
hsize_t *count = NULL;
hsize_t numelem;
hsize_t total_size[H5S_MAX_RANK];
size_t type_size;
hid_t sid1 = H5I_INVALID_HID;
hid_t mem_space = H5I_INVALID_HID;
void *region_buf = NULL;
int blkndx;
int jndx;
int ret_value = SUCCEED;
/* Get the dataspace of the dataset */
if ((sid1 = H5Dget_space(region_id)) < 0) {
ret_value = FAIL;
goto done;
}
/* Allocate space for the dimension array */
if (NULL == (dims1 = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims))) {
ret_value = FAIL;
goto done;
}
/* Find the dimensions of each data space from the block coordinates */
for (jndx = 0, numelem = 1; jndx < ndims; jndx++) {
dims1[jndx] = ptdata[jndx + ndims] - ptdata[jndx] + 1;
numelem = dims1[jndx] * numelem;
}
/* Create dataspace for reading buffer */
if ((mem_space = H5Screate_simple(ndims, dims1, NULL)) < 0) {
ret_value = FAIL;
goto done;
}
if (!(type_size = H5Tget_size(type_id))) {
ret_value = FAIL;
goto done;
}
if (NULL == (region_buf = malloc(type_size * (size_t)numelem))) {
ret_value = FAIL;
goto done;
}
/* Select (x , x , ..., x ) x (y , y , ..., y ) hyperslab for reading memory dataset */
/* 1 2 n 1 2 n */
if (NULL == (start = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims))) {
ret_value = FAIL;
goto done;
}
if (NULL == (count = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims))) {
ret_value = FAIL;
goto done;
}
for (blkndx = 0; blkndx < nblocks; blkndx++) {
for (jndx = 0; jndx < ndims; jndx++) {
start[jndx] = ptdata[jndx + blkndx * ndims * 2];
count[jndx] = dims1[jndx];
}
if (H5Sselect_hyperslab(sid1, H5S_SELECT_SET, start, NULL, count, NULL) < 0) {
ret_value = FAIL;
goto done;
}
if (H5Dread(region_id, type_id, mem_space, sid1, H5P_DEFAULT, region_buf) < 0) {
ret_value = FAIL;
goto done;
}
if (H5Sget_simple_extent_dims(mem_space, total_size, NULL) < 0) {
ret_value = FAIL;
goto done;
}
if (h5str_render_bin_output(stream, container, type_id, (char *)region_buf, numelem) < 0) {
ret_value = FAIL;
goto done;
}
/* Render the region data element end */
} /* end for (blkndx = 0; blkndx < nblocks; blkndx++) */
done:
if (count)
free(count);
if (start)
free(start);
if (region_buf)
free(region_buf);
if (mem_space >= 0)
H5Sclose(mem_space);
if (dims1)
free(dims1);
if (sid1 >= 0)
H5Sclose(sid1);
return ret_value;
} /* end render_bin_output_region_data_blocks */
/*-------------------------------------------------------------------------
* Purpose: Print some values from a dataset referenced by region blocks.
*
* Description:
* This is a special case subfunction to dump a region reference using blocks.
*
* Return:
* The function returns False if ERROR, otherwise True
*
*-------------------------------------------------------------------------
*/
static int
render_bin_output_region_blocks(FILE *stream, hid_t region_space, hid_t region_id, hid_t container)
{
hssize_t nblocks;
hsize_t alloc_size;
hsize_t *ptdata = NULL;
hid_t dtype = H5I_INVALID_HID;
hid_t type_id = H5I_INVALID_HID;
int ndims;
int ret_value = SUCCEED;
if ((nblocks = H5Sget_select_hyper_nblocks(region_space)) < 0) {
ret_value = FAIL;
goto done;
}
if (nblocks > 0) {
/* Print block information */
if ((ndims = H5Sget_simple_extent_ndims(region_space)) < 0) {
ret_value = FAIL;
goto done;
}
alloc_size = (hsize_t)nblocks * (hsize_t)ndims * 2 * (hsize_t)sizeof(ptdata[0]);
if (NULL == (ptdata = (hsize_t *)malloc((size_t)alloc_size))) {
ret_value = FAIL;
goto done;
}
if (H5Sget_select_hyper_blocklist(region_space, (hsize_t)0, (hsize_t)nblocks, ptdata) < 0) {
ret_value = FAIL;
goto done;
}
if ((dtype = H5Dget_type(region_id)) < 0) {
ret_value = FAIL;
goto done;
}
if ((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0) {
ret_value = FAIL;
goto done;
}
if (render_bin_output_region_data_blocks(stream, region_id, container, ndims, type_id, nblocks,
ptdata) < 0) {
ret_value = FAIL;
goto done;
}
}
done:
if (type_id >= 0)
H5Tclose(type_id);
if (dtype >= 0)
H5Tclose(dtype);
if (ptdata)
free(ptdata);
return ret_value;
} /* end render_bin_output_region_blocks */
/*-------------------------------------------------------------------------
* Purpose: Print the data values from a dataset referenced by region points.
*
* Description:
* This is a special case subfunction to print the data in a region reference of type points.
*
* Return:
* The function returns FAIL on error, otherwise SUCCEED
*
*-------------------------------------------------------------------------
*/
static int
render_bin_output_region_data_points(FILE *stream, hid_t region_space, hid_t region_id, hid_t container,
int ndims, hid_t type_id, hssize_t npoints, hsize_t *ptdata)
{
hsize_t *dims1 = NULL;
size_t type_size;
hid_t mem_space = H5I_INVALID_HID;
void *region_buf = NULL;
int ret_value = SUCCEED;
UNUSED(ptdata);
if (!(type_size = H5Tget_size(type_id))) {
ret_value = FAIL;
goto done;
}
if (NULL == (region_buf = malloc(type_size * (size_t)npoints))) {
ret_value = FAIL;
goto done;
}
/* Allocate space for the dimension array */
if (NULL == (dims1 = (hsize_t *)malloc(sizeof(hsize_t) * (size_t)ndims))) {
ret_value = FAIL;
goto done;
}
dims1[0] = (hsize_t)npoints;
if ((mem_space = H5Screate_simple(1, dims1, NULL)) < 0) {
ret_value = FAIL;
goto done;
}
if (H5Dread(region_id, type_id, mem_space, region_space, H5P_DEFAULT, region_buf) < 0) {
ret_value = FAIL;
goto done;
}
if (H5Sget_simple_extent_dims(region_space, dims1, NULL) < 0) {
ret_value = FAIL;
goto done;
}
if (h5str_render_bin_output(stream, container, type_id, (char *)region_buf, (hsize_t)npoints) < 0) {
ret_value = FAIL;
goto done;
}
done:
if (dims1)
free(dims1);
if (mem_space >= 0)
H5Sclose(mem_space);
if (region_buf)
free(region_buf);
return ret_value;
} /* end render_bin_output_region_data_points */
/*-------------------------------------------------------------------------
* Purpose: Print some values from a dataset referenced by region points.
*
* Description:
* This is a special case subfunction to dump a region reference using points.
*
* Return:
* The function returns False if the last dimension has been reached, otherwise True
*
*-------------------------------------------------------------------------
*/
static int
render_bin_output_region_points(FILE *stream, hid_t region_space, hid_t region_id, hid_t container)
{
hssize_t npoints;
hsize_t alloc_size;
hsize_t *ptdata = NULL;
hid_t dtype = H5I_INVALID_HID;
hid_t type_id = H5I_INVALID_HID;
int ndims;
int ret_value = SUCCEED;
if ((npoints = H5Sget_select_elem_npoints(region_space)) < 0) {
ret_value = FAIL;
goto done;
}
if (npoints > 0) {
/* Allocate space for the dimension array */
if ((ndims = H5Sget_simple_extent_ndims(region_space)) < 0) {
ret_value = FAIL;
goto done;
}
alloc_size = (hsize_t)npoints * (hsize_t)ndims * (hsize_t)sizeof(ptdata[0]);
if (NULL == (ptdata = (hsize_t *)malloc((size_t)alloc_size))) {
ret_value = FAIL;
goto done;
}
if (H5Sget_select_elem_pointlist(region_space, (hsize_t)0, (hsize_t)npoints, ptdata) < 0) {
ret_value = FAIL;
goto done;
}
if ((dtype = H5Dget_type(region_id)) < 0) {
ret_value = FAIL;
goto done;
}
if ((type_id = H5Tget_native_type(dtype, H5T_DIR_DEFAULT)) < 0) {
ret_value = FAIL;
goto done;
}
if (render_bin_output_region_data_points(stream, region_space, region_id, container, ndims, type_id,
npoints, ptdata) < 0) {
ret_value = FAIL;
goto done;
}
}
done:
if (type_id >= 0)
H5Tclose(type_id);
if (dtype >= 0)
H5Tclose(dtype);
if (ptdata)
free(ptdata);
return ret_value;
} /* end render_bin_output_region_points */
/*-------------------------------------------------------------------------
* Purpose: Print some values from an attribute referenced by object reference.
*
* Parameters Description:
* FILE *buffer is the string into which to render
*-------------------------------------------------------------------------
*/
static int
h5str_dump_region_attribute(JNIEnv *env, h5str_t *str, hid_t region_id)
{
int ret_value = SUCCEED;
hid_t atype = H5I_INVALID_HID;
hid_t type_id = H5I_INVALID_HID;
hid_t region_space = H5I_INVALID_HID;
hsize_t total_size[H5S_MAX_RANK]; /* total size of dataset*/
size_t i; /* counter */
size_t size; /* datum size */
int sndims; /* rank of dataspace */
hsize_t p_nelmts; /* total selected elmts */
hsize_t alloc_size;
unsigned char *buf = NULL; /* buffer for raw data */
/* VL data special information */
unsigned int vl_data = 0; /* contains VL datatypes */
if ((region_space = H5Aget_space(region_id)) < 0) {
ret_value = FAIL;
goto done;
}
if ((sndims = H5Sget_simple_extent_ndims(region_space)) < 0) {
ret_value = FAIL;
goto done;
}
/* Assume entire data space to be read */
H5Sget_simple_extent_dims(region_space, total_size, NULL);
p_nelmts = 1;
for (i = 0; i < (size_t)sndims; i++)
p_nelmts *= total_size[i];
if ((atype = H5Aget_type(region_id)) < 0) {
ret_value = FAIL;
goto done;
}
if ((type_id = H5Tget_native_type(atype, H5T_DIR_DEFAULT)) < 0) {
ret_value = FAIL;
goto done;
}
/* Check if we have VL data in the dataset's datatype */
if (h5str_detect_vlen(type_id) == true)
vl_data = true;
if (!(size = H5Tget_size(type_id))) {
ret_value = FAIL;
goto done;
}
alloc_size = p_nelmts * size;
assert(alloc_size == (hsize_t)((size_t)alloc_size)); /*check for overflow*/
if (NULL != (buf = (unsigned char *)malloc((size_t)alloc_size))) {
/* Read the data */
if (H5Aread(region_id, type_id, buf) >= 0) {
for (i = 0; i < p_nelmts; i++) {
size_t bytes_in = 0; /* # of bytes to write */
void *memref = buf + i * size;
if (!(bytes_in = h5str_sprintf(ENVONLY, str, region_id, type_id, memref, 1)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((i < p_nelmts - 1) && (bytes_in > 0)) {
if (!h5str_append(str, ", "))
H5_ASSERTION_ERROR(ENVONLY, "Unable to append string.");
}
}
/* Reclaim any VL memory, if necessary */
if (vl_data) {
if (H5Treclaim(type_id, region_space, H5P_DEFAULT, buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
}
else
H5_LIBRARY_ERROR(ENVONLY);
}
done:
if (buf)
free(buf);
if (region_space >= 0)
H5Sclose(region_space);
if (type_id >= 0)
H5Tclose(type_id);
if (atype >= 0)
H5Tclose(type_id);
return ret_value;
}
int
h5str_dump_simple_dset(JNIEnv *env, FILE *stream, hid_t dset, int binary_order)
{
hid_t f_space = H5I_INVALID_HID; /* file data space */
hsize_t elmtno; /* counter */
size_t i = 0; /* counter */
int sndims; /* rank of dataspace */
int carry; /* counter carry value */
hsize_t zero[8]; /* vector of zeros */
hsize_t total_size[H5S_MAX_RANK]; /* total size of dataset*/
/* Stripmine info */
hsize_t sm_size[H5S_MAX_RANK]; /* stripmine size */
hsize_t sm_nbytes; /* bytes per stripmine */
hsize_t sm_nelmts; /* elements per stripmine */
unsigned char *sm_buf = NULL; /* buffer for raw data */
hid_t sm_space = H5I_INVALID_HID; /* stripmine data space */
/* Hyperslab info */
hsize_t hs_offset[H5S_MAX_RANK]; /* starting offset */
hsize_t hs_size[H5S_MAX_RANK]; /* size this pass */
hsize_t hs_nelmts; /* elements in request */
/* VL data special information */
unsigned int vl_data = 0; /* contains VL datatypes */
int ret_value = FAIL;
hid_t p_type = H5I_INVALID_HID;
hid_t f_type = H5I_INVALID_HID;
if (dset < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_dump_simple_dset: dset ID < 0");
if ((f_type = H5Dget_type(dset)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((f_space = H5Dget_space(dset)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((sndims = H5Sget_simple_extent_ndims(f_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Assume entire data space to be printed */
if (H5Sget_simple_extent_dims(f_space, total_size, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tequal(f_type, H5T_STD_REF_DSETREG)) {
hssize_t p_nelmts; /* total selected elmts */
if ((p_nelmts = H5Sget_simple_extent_npoints(f_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (NULL ==
(sm_buf = (unsigned char *)calloc(MAX(sizeof(unsigned), sizeof(H5R_ref_t)), (size_t)p_nelmts)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_simple_mem: failed to allocate sm_buf");
/* Read the data */
if (H5Dread(dset, H5T_STD_REF, H5S_ALL, H5S_ALL, H5P_DEFAULT, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (binary_order == 99) {
if (h5str_dump_simple_data(ENVONLY, stream, dset, H5T_STD_REF, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (h5str_render_bin_output(stream, dset, H5T_STD_REF, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
}
else {
/* Print info */
size_t p_type_nbytes; /* size of memory type */
hsize_t p_nelmts; /* total selected elmts */
switch (binary_order) {
case 1: {
if ((p_type = h5str_get_native_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case 2: {
if ((p_type = h5str_get_little_endian_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case 3: {
if ((p_type = h5str_get_big_endian_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
default: {
if ((p_type = H5Tcopy(f_type)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
break;
}
}
/* Calculate the number of elements we're going to print */
p_nelmts = 1;
if (sndims > 0) {
for (i = 0; i < (size_t)sndims; i++)
p_nelmts *= total_size[i];
} /* end if */
if (p_nelmts > 0) {
/* Check if we have VL data in the dataset's datatype */
if (h5str_detect_vlen(p_type) != 0)
vl_data = 1;
/*
* Determine the strip mine size and allocate a buffer. The strip mine is
* a hyperslab whose size is manageable.
*/
if (!(sm_nbytes = p_type_nbytes = H5Tget_size(p_type)))
H5_LIBRARY_ERROR(ENVONLY);
if (sndims > 0) {
for (i = (size_t)sndims; i > 0; --i) {
hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes;
if (size == 0) /* datum size > H5TOOLS_BUFSIZE */
size = 1;
sm_size[i - 1] = (((total_size[i - 1]) < (size)) ? (total_size[i - 1]) : (size));
sm_nbytes *= sm_size[i - 1];
}
}
if (sm_nbytes > 0) {
if (NULL == (sm_buf = (unsigned char *)malloc((size_t)sm_nbytes)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_simple_dset: failed to allocate sm_buf");
sm_nelmts = sm_nbytes / p_type_nbytes;
if ((sm_space = H5Screate_simple(1, &sm_nelmts, NULL)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* The stripmine loop */
memset(hs_offset, 0, sizeof hs_offset);
memset(zero, 0, sizeof zero);
for (elmtno = 0; elmtno < (hsize_t)p_nelmts; elmtno += hs_nelmts) {
/* Calculate the hyperslab size */
if (sndims > 0) {
for (i = 0, hs_nelmts = 1; i < (size_t)sndims; i++) {
hs_size[i] = (((total_size[i] - hs_offset[i]) < (sm_size[i]))
? (total_size[i] - hs_offset[i])
: (sm_size[i]));
hs_nelmts *= hs_size[i];
}
if (H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &hs_nelmts, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
else {
if (H5Sselect_all(f_space) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Sselect_all(sm_space) < 0)
H5_LIBRARY_ERROR(ENVONLY);
hs_nelmts = 1;
}
/* Read the data */
if (H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (binary_order == 99) {
if (h5str_dump_simple_data(ENVONLY, stream, dset, p_type, sm_buf, hs_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (h5str_render_bin_output(stream, dset, p_type, sm_buf, hs_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
/* Reclaim any VL memory, if necessary */
if (vl_data) {
if (H5Treclaim(p_type, sm_space, H5P_DEFAULT, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
/* Calculate the next hyperslab offset */
for (i = (size_t)sndims, carry = 1; i > 0 && carry; --i) {
hs_offset[i - 1] += hs_size[i - 1];
if (hs_offset[i - 1] == total_size[i - 1])
hs_offset[i - 1] = 0;
else
carry = 0;
}
}
}
}
}
ret_value = SUCCEED;
done:
if (sm_space >= 0)
H5Sclose(sm_space);
if (sm_buf)
free(sm_buf);
if (f_space >= 0)
H5Sclose(f_space);
if (p_type >= 0)
H5Tclose(p_type);
if (f_type >= 0)
H5Tclose(f_type);
return ret_value;
} /* end h5str_dump_simple_dset */
int
h5str_dump_simple_mem(JNIEnv *env, FILE *stream, hid_t attr_id, int binary_order)
{
hid_t f_space = H5I_INVALID_HID; /* file data space */
hsize_t alloc_size;
int sndims; /* rank of dataspace */
unsigned i; /* counters */
hsize_t total_size[H5S_MAX_RANK]; /* total size of dataset */
int ret_value = 0;
unsigned char *sm_buf = NULL; /* buffer for raw data */
/* VL data special information */
unsigned int vl_data = 0; /* contains VL datatypes */
hid_t p_type = H5I_INVALID_HID;
hid_t f_type = H5I_INVALID_HID;
if (attr_id < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_dump_simple_mem: attr ID < 0");
if ((f_type = H5Aget_type(attr_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5I_INVALID_HID == (f_space = H5Aget_space(attr_id)))
H5_LIBRARY_ERROR(ENVONLY);
if ((sndims = H5Sget_simple_extent_ndims(f_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Sget_simple_extent_dims(f_space, total_size, NULL) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tequal(f_type, H5T_STD_REF_DSETREG)) {
hssize_t p_nelmts; /* total selected elmts */
if ((p_nelmts = H5Sget_simple_extent_npoints(f_space)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (NULL ==
(sm_buf = (unsigned char *)calloc(MAX(sizeof(unsigned), sizeof(H5R_ref_t)), (size_t)p_nelmts)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_simple_mem: failed to allocate sm_buf");
/* Read the data */
if (H5Aread(attr_id, H5T_STD_REF, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (binary_order == 99) {
if (h5str_dump_simple_data(ENVONLY, stream, attr_id, H5T_STD_REF, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (h5str_render_bin_output(stream, attr_id, H5T_STD_REF, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
}
else {
hsize_t p_nelmts; /* total selected elmts */
switch (binary_order) {
case 1: {
if ((p_type = h5str_get_native_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case 2: {
if ((p_type = h5str_get_little_endian_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case 3: {
if ((p_type = h5str_get_big_endian_type(f_type)) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
default: {
if ((p_type = H5Tcopy(f_type)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
break;
}
}
/* Calculate the number of elements we're going to print */
p_nelmts = 1;
if (sndims > 0) {
for (i = 0; i < (size_t)sndims; i++)
p_nelmts *= total_size[i];
} /* end if */
if (p_nelmts > 0) {
/* Check if we have VL data in the dataset's datatype */
if (h5str_detect_vlen(p_type) != 0)
vl_data = 1;
alloc_size = (size_t)p_nelmts * H5Tget_size(p_type);
if (NULL == (sm_buf = (unsigned char *)malloc((size_t)alloc_size)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_simple_mem: failed to allocate sm_buf");
/* Read the data */
if (H5Aread(attr_id, p_type, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (binary_order == 99) {
if (h5str_dump_simple_data(ENVONLY, stream, attr_id, p_type, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
else {
if (h5str_render_bin_output(stream, attr_id, p_type, sm_buf, (size_t)p_nelmts) < 0)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
}
/* Reclaim any VL memory, if necessary */
if (vl_data) {
if (H5Treclaim(p_type, f_space, H5P_DEFAULT, sm_buf) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
}
}
ret_value = SUCCEED;
done:
if (sm_buf)
free(sm_buf);
if (f_space >= 0)
H5Sclose(f_space);
if (p_type >= 0)
H5Tclose(p_type);
if (f_type >= 0)
H5Tclose(f_type);
return ret_value;
}
/*-------------------------------------------------------------------------
* Function: H5Tdetect_variable_str
*
* Purpose: Recursive check for variable length string of a datatype.
*
* Return: true : type contains any variable length string
* false : type doesn't contain any variable length string
* Negative value: failed
*-------------------------------------------------------------------------
*/
htri_t
H5Tdetect_variable_str(hid_t tid)
{
H5T_class_t tclass = -1;
htri_t ret = false;
ret = H5Tis_variable_str(tid);
if ((ret == true) || (ret < 0))
goto done;
tclass = H5Tget_class(tid);
if (tclass == H5T_ARRAY || tclass == H5T_VLEN) {
hid_t btid = H5Tget_super(tid);
if (btid < 0) {
ret = (htri_t)btid;
goto done;
}
ret = H5Tdetect_variable_str(btid);
if ((ret == true) || (ret < 0)) {
H5Tclose(btid);
goto done;
}
}
else if (tclass == H5T_COMPOUND) {
unsigned nmembs;
int snmembs = H5Tget_nmembers(tid);
unsigned u;
if (snmembs < 0) {
ret = FAIL;
goto done;
}
nmembs = (unsigned)snmembs;
for (u = 0; u < nmembs; u++) {
hid_t mtid = H5Tget_member_type(tid, u);
ret = H5Tdetect_variable_str(mtid);
if ((ret == true) || (ret < 0)) {
H5Tclose(mtid);
goto done;
}
H5Tclose(mtid);
}
}
done:
return ret;
} /* end H5Tdetect_variable_str */
static int
h5str_dump_simple_data(JNIEnv *env, FILE *stream, hid_t container, hid_t type, void *_mem, hsize_t nelmts)
{
unsigned char *mem = (unsigned char *)_mem;
h5str_t buffer; /* string into which to render */
hsize_t i; /* element counter */
size_t size; /* datum size */
int line_count;
int ret_value = 0;
if (!(size = H5Tget_size(type)))
H5_LIBRARY_ERROR(ENVONLY);
for (i = 0, line_count = 0; i < nelmts; i++, line_count++) {
size_t bytes_in = 0; /* # of bytes to write */
void *memref = mem + i * size;
/* Render the data element*/
h5str_new(&buffer, 32 * size);
if (!buffer.s)
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_dump_simple_data: failed to allocate buffer");
if (!(bytes_in = h5str_sprintf(ENVONLY, &buffer, container, type, memref, 1)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if ((i > 0) && (bytes_in > 0)) {
if (fprintf(stream, ", ") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_simple_data: fprintf failure");
if (line_count >= H5TOOLS_TEXT_BLOCK) {
line_count = 0;
if (fprintf(stream, "\n") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_simple_data: fprintf failure");
}
}
if (fprintf(stream, "%s", buffer.s) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_simple_data: fprintf failure");
h5str_free(&buffer);
} /* end for (i = 0; i < nelmts... */
if (fprintf(stream, "\n") < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "h5str_dump_simple_data: fprintf failure");
done:
if (buffer.s)
h5str_free(&buffer);
return ret_value;
} /* end h5str_dump_simple_data */
/*
* Utility Java APIs
* Functions designed to workaround issues with the Java-C interface
*/
/*
* Class: hdf_hdf5lib_H5
* Method: H5AreadComplex
* Signature: (JJ[Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_H5_H5AreadComplex(JNIEnv *env, jclass clss, jlong attr_id, jlong mem_type_id,
jobjectArray buf)
{
h5str_t h5str;
jstring jstr;
size_t size;
size_t i;
hid_t p_type = H5I_INVALID_HID;
jsize n;
char *readBuf = NULL;
herr_t status = FAIL;
UNUSED(clss);
memset(&h5str, 0, sizeof(h5str_t));
if ((p_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
size = (((H5Tget_size(mem_type_id)) > (H5Tget_size(p_type))) ? (H5Tget_size(mem_type_id))
: (H5Tget_size(p_type)));
if ((n = ENVPTR->GetArrayLength(ENVONLY, buf)) <= 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "H5AreadComplex: read buffer length <= 0");
if (NULL == (readBuf = (char *)malloc((size_t)n * size)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5AreadComplex: failed to allocate read buffer");
if ((status = H5Aread(attr_id, mem_type_id, readBuf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
h5str_new(&h5str, 4 * size);
if (!h5str.s)
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5AreadComplex: failed to allocate string buffer");
for (i = 0; i < (size_t)n; i++) {
h5str.s[0] = '\0';
if (!h5str_sprintf(ENVONLY, &h5str, attr_id, mem_type_id, readBuf + (i * size), 0))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (NULL == (jstr = ENVPTR->NewStringUTF(ENVONLY, h5str.s)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->SetObjectArrayElement(ENVONLY, buf, (jsize)i, jstr);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->DeleteLocalRef(ENVONLY, jstr);
} /* end for */
done:
if (h5str.s)
h5str_free(&h5str);
if (readBuf)
free(readBuf);
if (p_type >= 0)
H5Tclose(p_type);
return status;
}
/*
* Copies the content of one attribute to another attribute
* Class: hdf_hdf5lib_H5
* Method: H5Acopy
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_H5_H5Acopy(JNIEnv *env, jclass clss, jlong src_id, jlong dst_id)
{
hssize_t npoints;
hsize_t total_size = 0;
size_t type_size;
jbyte *buf = NULL;
hid_t tid = H5I_INVALID_HID;
hid_t sid = H5I_INVALID_HID;
herr_t retVal = FAIL;
UNUSED(clss);
if ((sid = H5Aget_space((hid_t)src_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((tid = H5Aget_type((hid_t)src_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((npoints = H5Sget_simple_extent_npoints(sid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(type_size = H5Tget_size(tid)))
H5_LIBRARY_ERROR(ENVONLY);
total_size = (hsize_t)npoints * (hsize_t)type_size;
if (NULL == (buf = (jbyte *)malloc((size_t)total_size * sizeof(jbyte))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Acopy: failed to allocate buffer");
if ((retVal = H5Aread((hid_t)src_id, tid, buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tclose(tid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
tid = H5I_INVALID_HID;
if ((tid = H5Aget_type((hid_t)dst_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((retVal = H5Awrite((hid_t)dst_id, tid, buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
done:
if (buf)
free(buf);
if (tid >= 0)
H5Tclose(tid);
if (sid >= 0)
H5Sclose(sid);
return (jint)retVal;
} /* end Java_hdf_hdf5lib_H5_H5Acopy */
/*
* 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 *env, jclass clss, jlong src_id, jlong dst_id)
{
hssize_t npoints;
hsize_t total_size = 0, total_allocated_size;
size_t type_size;
jbyte *buf = NULL;
hid_t tid = H5I_INVALID_HID;
hid_t sid = H5I_INVALID_HID;
herr_t retVal = FAIL;
UNUSED(clss);
if (!(total_allocated_size = H5Dget_storage_size((hid_t)src_id)))
return 0; /* nothing to write */
if ((sid = H5Dget_space((hid_t)src_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((tid = H5Dget_type((hid_t)src_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((npoints = H5Sget_simple_extent_npoints(sid)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(type_size = H5Tget_size(tid)))
H5_LIBRARY_ERROR(ENVONLY);
total_size = (hsize_t)npoints * (hsize_t)type_size;
if (NULL == (buf = (jbyte *)malloc((size_t)total_size * sizeof(jbyte))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Dcopy: failed to allocate buffer");
if ((retVal = H5Dread((hid_t)src_id, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (H5Tclose(tid) < 0)
H5_LIBRARY_ERROR(ENVONLY);
tid = H5I_INVALID_HID;
if ((tid = H5Dget_type((hid_t)dst_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((retVal = H5Dwrite((hid_t)dst_id, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
done:
if (buf)
free(buf);
if (tid >= 0)
H5Tclose(tid);
if (sid >= 0)
H5Sclose(sid);
return (jint)retVal;
} /* end Java_hdf_hdf5lib_H5_H5Dcopy */
/*
* /////////////////////////////////////////////////////////////////////////////////
* //
* //
* // Add these methods so that we don't need to call H5Gget_objtype_by_idx
* // in a loop to get information for all the objects in a group, which takes
* // a lot of time to finish if the number of objects is more than 10,000
* //
* /////////////////////////////////////////////////////////////////////////////////
*/
#ifdef __cplusplus
herr_t obj_info_all(hid_t g_id, const char *name, const H5L_info2_t *linfo, void *op_data);
herr_t obj_info_max(hid_t g_id, const char *name, const H5L_info2_t *linfo, void *op_data);
int H5Gget_obj_info_max(hid_t, char **, int *, int *, H5O_token_t *, long);
int H5Gget_obj_info_full(hid_t loc_id, char **objname, int *otype, int *ltype, unsigned long *fno,
H5O_token_t *obj_token, int indexType, int indexOrder);
#else
static herr_t obj_info_all(hid_t g_id, const char *name, const H5L_info2_t *linfo, void *op_data);
static herr_t obj_info_max(hid_t g_id, const char *name, const H5L_info2_t *linfo, void *op_data);
static int H5Gget_obj_info_max(hid_t, char **, int *, int *, H5O_token_t *, long);
static int H5Gget_obj_info_full(hid_t loc_id, char **objname, int *otype, int *ltype, unsigned long *fno,
H5O_token_t *obj_token, int indexType, int indexOrder);
#endif
typedef struct info_all {
char **objname;
int *otype;
int *ltype;
H5O_token_t *obj_token;
unsigned long *fno;
unsigned long idxnum;
int count;
} info_all_t;
/*
* Class: hdf_hdf5lib_H5
* Method: H5Gget_obj_info_full
* Signature: (JLjava/lang/String;[Ljava/lang/String;[I[I[J[JIII)I
*/
/*
* NOTE: This is a dangerous call! The caller can supply any value they'd like
* for 'n' and if it exceeds the number of links in the group, we will most likely
* end up overwriting memory heap-tracking info.
*/
JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1full(JNIEnv *env, jclass clss, jlong loc_id, jstring group_name,
jobjectArray objName, jintArray oType, jintArray lType,
jlongArray fNo, jobjectArray oToken, jint n, jint indx_type,
jint indx_order)
{
unsigned long *fnos = NULL;
H5O_token_t *tokens = NULL;
const char *gName = NULL;
char **oName = NULL;
jboolean isCopy;
jstring str;
jobject token;
jint *otarr = NULL;
jint *ltarr = NULL;
jlong *fnoP = NULL;
hid_t gid = (hid_t)loc_id;
int i;
int indexType = indx_type;
int indexOrder = indx_order;
herr_t ret_val = FAIL;
UNUSED(clss);
if (NULL == oType)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_full: oType is NULL");
if (NULL == lType)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_full: lType is NULL");
if (NULL == oToken)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_full: oToken is NULL");
if (NULL == fNo)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_full: fNo is NULL");
PIN_INT_ARRAY(ENVONLY, oType, otarr, &isCopy, "H5Gget_obj_info_full: oType not pinned");
PIN_INT_ARRAY(ENVONLY, lType, ltarr, &isCopy, "H5Gget_obj_info_full: lType not pinned");
PIN_LONG_ARRAY(ENVONLY, fNo, fnoP, &isCopy, "H5Gget_obj_info_full: fNo not pinned");
if (NULL == (oName = (char **)calloc((size_t)n, sizeof(*oName))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Gget_obj_info_full: failed to allocate buffer for object name");
if (NULL == (tokens = (H5O_token_t *)calloc((size_t)n, sizeof(H5O_token_t))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Gget_obj_info_full: failed to allocate buffer for object tokens");
if (NULL == (fnos = (unsigned long *)calloc((size_t)n, sizeof(unsigned long))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY,
"H5Gget_obj_info_full: failed to allocate buffer for file number info");
if (group_name) {
PIN_JAVA_STRING(ENVONLY, group_name, gName, &isCopy, "H5Gget_obj_info_full: group_name not pinned");
if ((gid = H5Gopen2((hid_t)loc_id, gName, H5P_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
}
if ((ret_val = H5Gget_obj_info_full(gid, oName, (int *)otarr, (int *)ltarr, fnos, tokens, indexType,
indexOrder)) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "H5Gget_obj_info_full: retrieval of object info failed");
for (i = 0; i < n; i++) {
fnoP[i] = (jlong)fnos[i];
if (oName[i]) {
if (NULL == (str = ENVPTR->NewStringUTF(ENVONLY, oName[i])))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->SetObjectArrayElement(ENVONLY, objName, i, (jobject)str);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->DeleteLocalRef(ENVONLY, str);
} /* end if */
/* Create an H5O_token_t object */
if (NULL == (token = create_H5O_token_t(ENVONLY, &tokens[i], true)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->SetObjectArrayElement(ENVONLY, oToken, i, token);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->DeleteLocalRef(ENVONLY, token);
}
done:
if (gName) {
H5Gclose(gid);
UNPIN_JAVA_STRING(ENVONLY, group_name, gName);
}
if (fnos)
free(fnos);
if (tokens)
free(tokens);
if (oName)
h5str_array_free(oName, (size_t)n);
if (fnoP)
UNPIN_LONG_ARRAY(ENVONLY, fNo, fnoP, (ret_val < 0) ? JNI_ABORT : 0);
if (ltarr)
UNPIN_INT_ARRAY(ENVONLY, lType, ltarr, (ret_val < 0) ? JNI_ABORT : 0);
if (otarr)
UNPIN_INT_ARRAY(ENVONLY, oType, otarr, (ret_val < 0) ? JNI_ABORT : 0);
return ret_val;
} /* end Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1full */
/*
* Class: hdf_hdf5lib_H5
* Method: H5Gget_obj_info_max
* Signature: (J[Ljava/lang/String;[I[I[JJI)I
*/
/*
* NOTE: This is a dangerous call! The caller can supply any value they'd like
* for 'n' and if it exceeds the number of links reachable from the group, we
* will most likely end up overwriting memory heap-tracking info.
*/
JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1max(JNIEnv *env, jclass clss, jlong loc_id, jobjectArray objName,
jintArray oType, jintArray lType, jobjectArray oToken,
jlong maxnum, jint n)
{
H5O_token_t *tokens = NULL;
jboolean isCopy;
jstring str;
jobject token;
char **oName = NULL;
jint *otarr = NULL;
jint *ltarr = NULL;
int i;
herr_t ret_val = FAIL;
UNUSED(clss);
if (NULL == oType)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_max: oType is NULL");
if (NULL == lType)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_max: lType is NULL");
if (NULL == oToken)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5Gget_obj_info_max: oToken is NULL");
PIN_INT_ARRAY(ENVONLY, oType, otarr, &isCopy, "H5Gget_obj_info_max: oType not pinned");
PIN_INT_ARRAY(ENVONLY, lType, ltarr, &isCopy, "H5Gget_obj_info_max: lType not pinned");
if (NULL == (oName = (char **)calloc((size_t)n, sizeof(*oName))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Gget_obj_info_max: failed to allocate buffer for object name");
if (NULL == (tokens = (H5O_token_t *)calloc((size_t)n, sizeof(H5O_token_t))))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "H5Gget_obj_info_max: failed to allocate buffer for object tokens");
if ((ret_val = H5Gget_obj_info_max((hid_t)loc_id, oName, (int *)otarr, (int *)ltarr, tokens, maxnum)) < 0)
H5_JNI_FATAL_ERROR(ENVONLY, "H5Gget_obj_info_max: retrieval of object info failed");
for (i = 0; i < n; i++) {
if (oName[i]) {
if (NULL == (str = ENVPTR->NewStringUTF(ENVONLY, oName[i])))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->SetObjectArrayElement(ENVONLY, objName, i, (jobject)str);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->DeleteLocalRef(ENVONLY, str);
}
/* Create an H5O_token_t object */
if (NULL == (token = create_H5O_token_t(ENVONLY, &tokens[i], true)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->SetObjectArrayElement(ENVONLY, oToken, i, token);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
ENVPTR->DeleteLocalRef(ENVONLY, token);
} /* end for */
done:
if (tokens)
free(tokens);
if (oName)
h5str_array_free(oName, (size_t)n);
if (ltarr)
UNPIN_INT_ARRAY(ENVONLY, lType, ltarr, (ret_val < 0) ? JNI_ABORT : 0);
if (otarr)
UNPIN_INT_ARRAY(ENVONLY, oType, otarr, (ret_val < 0) ? JNI_ABORT : 0);
return ret_val;
} /* end Java_hdf_hdf5lib_H5_H5Gget_1obj_1info_1max */
int
H5Gget_obj_info_full(hid_t loc_id, char **objname, int *otype, int *ltype, unsigned long *fno,
H5O_token_t *obj_token, int indexType, int indexOrder)
{
info_all_t info;
info.objname = objname;
info.otype = otype;
info.ltype = ltype;
info.idxnum = 0;
info.fno = fno;
info.obj_token = obj_token;
info.count = 0;
if (H5Literate2(loc_id, (H5_index_t)indexType, (H5_iter_order_t)indexOrder, NULL, obj_info_all,
(void *)&info) < 0) {
/*
* Reset info stats; most importantly, reset the count.
*/
info.objname = objname;
info.otype = otype;
info.ltype = ltype;
info.idxnum = 0;
info.fno = fno;
info.obj_token = obj_token;
info.count = 0;
/* Iteration failed, try normal alphabetical order */
if (H5Literate2(loc_id, H5_INDEX_NAME, H5_ITER_INC, NULL, obj_info_all, (void *)&info) < 0)
return -1;
}
return info.count;
} /* end H5Gget_obj_info_full */
int
H5Gget_obj_info_max(hid_t loc_id, char **objname, int *otype, int *ltype, H5O_token_t *obj_token, long maxnum)
{
info_all_t info;
info.objname = objname;
info.otype = otype;
info.ltype = ltype;
info.idxnum = (unsigned long)maxnum;
info.obj_token = obj_token;
info.count = 0;
if (H5Lvisit2(loc_id, H5_INDEX_NAME, H5_ITER_NATIVE, obj_info_max, (void *)&info) < 0)
return -1;
return info.count;
} /* end H5Gget_obj_info_max */
herr_t
obj_info_all(hid_t loc_id, const char *name, const H5L_info2_t *info, void *op_data)
{
info_all_t *datainfo = (info_all_t *)op_data;
H5O_info2_t object_info;
htri_t object_exists;
datainfo->otype[datainfo->count] = -1;
datainfo->ltype[datainfo->count] = -1;
datainfo->obj_token[datainfo->count] = H5O_TOKEN_UNDEF;
if (NULL == (datainfo->objname[datainfo->count] = strdup(name)))
goto done;
if ((object_exists = H5Oexists_by_name(loc_id, name, H5P_DEFAULT)) < 0)
goto done;
if (object_exists) {
if (H5Oget_info_by_name3(loc_id, name, &object_info, H5O_INFO_ALL, H5P_DEFAULT) < 0)
goto done;
datainfo->otype[datainfo->count] = object_info.type;
datainfo->ltype[datainfo->count] = info->type;
datainfo->fno[datainfo->count] = object_info.fileno;
memcpy(&datainfo->obj_token[datainfo->count], &object_info.token, sizeof(object_info.token));
}
done:
datainfo->count++;
return SUCCEED;
} /* end obj_info_all */
herr_t
obj_info_max(hid_t loc_id, const char *name, const H5L_info2_t *info, void *op_data)
{
info_all_t *datainfo = (info_all_t *)op_data;
H5O_info2_t object_info;
datainfo->otype[datainfo->count] = -1;
datainfo->ltype[datainfo->count] = -1;
datainfo->objname[datainfo->count] = NULL;
datainfo->obj_token[datainfo->count] = H5O_TOKEN_UNDEF;
/* This will be freed by h5str_array_free(oName, n) */
if (NULL == (datainfo->objname[datainfo->count] = strdup(name)))
goto done;
if (H5Oget_info3(loc_id, &object_info, H5O_INFO_ALL) < 0)
goto done;
datainfo->otype[datainfo->count] = object_info.type;
datainfo->ltype[datainfo->count] = info->type;
memcpy(&datainfo->obj_token[datainfo->count], &object_info.token, sizeof(object_info.token));
done:
datainfo->count++;
if (datainfo->count >= (int)datainfo->idxnum)
return 1;
else
return SUCCEED;
} /* end obj_info_max */
/*
* 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 *env, jclass clss, jstring file_export_name, jlong file_id,
jstring object_path, jint binary_order)
{
const char *file_export = NULL;
const char *object_name = NULL;
jboolean isCopy;
herr_t ret_val = FAIL;
hid_t dataset_id = H5I_INVALID_HID;
FILE *stream = NULL;
UNUSED(clss);
if (NULL == file_export_name)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5export_dataset: file_export_name is NULL");
if (NULL == object_path)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5export_dataset: object_path is NULL");
PIN_JAVA_STRING(ENVONLY, object_path, object_name, &isCopy, "H5export_dataset: object_path not pinned");
if ((dataset_id = H5Dopen2(file_id, object_name, H5P_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
PIN_JAVA_STRING(ENVONLY, file_export_name, file_export, NULL,
"H5export_dataset: file_export name not pinned");
if (NULL == (stream = fopen(file_export, "w+")))
H5_JNI_FATAL_ERROR(ENVONLY, "fopen failed");
if ((ret_val = h5str_dump_simple_dset(ENVONLY, stream, dataset_id, binary_order)) < 0)
H5_ASSERTION_ERROR(ENVONLY, "h5str_dump_simple_dset failed");
if (stream) {
fclose(stream);
stream = NULL;
}
done:
if (stream)
fclose(stream);
if (file_export)
UNPIN_JAVA_STRING(ENVONLY, file_export_name, file_export);
if (object_name)
UNPIN_JAVA_STRING(ENVONLY, object_path, object_name);
if (dataset_id >= 0)
H5Dclose(dataset_id);
} /* end Java_hdf_hdf5lib_H5_H5export_1dataset */
/*
* 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 *env, jclass clss, jstring file_export_name, jlong dset_id,
jstring attribute_name, jint binary_order)
{
const char *file_export = NULL;
const char *object_name = NULL;
jboolean isCopy;
herr_t ret_val = FAIL;
hid_t attr_id = H5I_INVALID_HID;
FILE *stream = NULL;
UNUSED(clss);
if (NULL == file_export_name)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5export_dataset: file_export_name is NULL");
if (NULL == attribute_name)
H5_NULL_ARGUMENT_ERROR(ENVONLY, "H5export_dataset: object_path is NULL");
PIN_JAVA_STRING(ENVONLY, attribute_name, object_name, &isCopy,
"H5export_dataset: object_path not pinned");
if ((attr_id = H5Aopen(dset_id, object_name, H5P_DEFAULT)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
PIN_JAVA_STRING(ENVONLY, file_export_name, file_export, NULL,
"H5export_dataset: file_export name not pinned");
if (NULL == (stream = fopen(file_export, "w+")))
H5_JNI_FATAL_ERROR(ENVONLY, "fopen failed");
if ((ret_val = h5str_dump_simple_mem(ENVONLY, stream, attr_id, binary_order)) < 0)
H5_ASSERTION_ERROR(ENVONLY, "h5str_dump_simple_dset failed");
if (stream) {
fclose(stream);
stream = NULL;
}
done:
if (stream)
fclose(stream);
if (file_export)
UNPIN_JAVA_STRING(ENVONLY, file_export_name, file_export);
if (object_name)
UNPIN_JAVA_STRING(ENVONLY, attribute_name, object_name);
if (attr_id >= 0)
H5Aclose(attr_id);
} /* 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, size_t buf_size)
{
jobject jobj = NULL;
hid_t memb = H5I_INVALID_HID;
jobjectArray jList = NULL;
H5T_class_t vlClass;
size_t vlSize;
size_t i;
size_t typeSize;
// raw_buf is normally bytes except when used for variable length strings
char *char_buf = (char *)raw_buf;
/* 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"); */
jclass cByte = ENVPTR->FindClass(ENVONLY, "java/lang/Byte");
jclass cShort = ENVPTR->FindClass(ENVONLY, "java/lang/Short");
jclass cInt = ENVPTR->FindClass(ENVONLY, "java/lang/Integer");
jclass cLong = ENVPTR->FindClass(ENVONLY, "java/lang/Long");
jclass cFloat = ENVPTR->FindClass(ENVONLY, "java/lang/Float");
jclass cDouble = ENVPTR->FindClass(ENVONLY, "java/lang/Double");
/*jobjectArray
jmethodID boolValueMid =
ENVPTR->GetStaticMethodID(ENVONLY, cBool, "valueOf", "(Z)Ljava/lang/Boolean;");
*/
jmethodID byteValueMid = ENVPTR->GetStaticMethodID(ENVONLY, cByte, "valueOf", "(B)Ljava/lang/Byte;");
jmethodID shortValueMid = ENVPTR->GetStaticMethodID(ENVONLY, cShort, "valueOf", "(S)Ljava/lang/Short;");
jmethodID intValueMid = ENVPTR->GetStaticMethodID(ENVONLY, cInt, "valueOf", "(I)Ljava/lang/Integer;");
jmethodID longValueMid = ENVPTR->GetStaticMethodID(ENVONLY, cLong, "valueOf", "(J)Ljava/lang/Long;");
jmethodID floatValueMid = ENVPTR->GetStaticMethodID(ENVONLY, cFloat, "valueOf", "(F)Ljava/lang/Float;");
jmethodID doubleValueMid =
ENVPTR->GetStaticMethodID(ENVONLY, cDouble, "valueOf", "(D)Ljava/lang/Double;");
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)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
/* Convert element to a list */
hvl_t vl_elem;
/* Get the number of sequence elements */
memcpy(&vl_elem, char_buf, sizeof(hvl_t));
jsize nelmts = (jsize)vl_elem.len;
if (vl_elem.len != (size_t)nelmts)
H5_JNI_FATAL_ERROR(ENVONLY, "translate_atomic_rbuf: overflow of number of VL elements");
if (nelmts < 0)
H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_rbuf: number of VL elements < 0");
/* 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");
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);
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");
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);
memb_offset = H5Tget_member_offset(mem_type_id, (unsigned int)i);
if ((memb_vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(memb_vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
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);
memb = H5I_INVALID_HID;
}
jobj = jList;
break;
} /* H5T_COMPOUND */
case H5T_ARRAY: {
void *objBuf = NULL;
size_t typeCount;
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
typeCount = typeSize / vlSize;
if (NULL == (objBuf = malloc(typeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer");
/* Convert each element */
/* Get the object element */
memcpy((char *)objBuf, char_buf, typeSize);
/* 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");
translate_rbuf(ENVONLY, jList, memb, vlClass, (jsize)typeCount, objBuf, typeSize);
jobj = jList;
if (objBuf)
free(objBuf);
break;
} /* H5T_ARRAY */
case H5T_ENUM:
case H5T_BITFIELD:
case H5T_INTEGER: {
/* Convert each element */
switch (typeSize) {
case sizeof(jbyte): {
jbyte byteValue;
memcpy(((char *)&byteValue), char_buf, typeSize);
if (NULL ==
(jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cByte, byteValueMid, byteValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case sizeof(jshort): {
jshort shortValue;
memcpy(((char *)&shortValue), char_buf, typeSize);
if (NULL ==
(jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cShort, shortValueMid, shortValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case sizeof(jint): {
jint intValue;
memcpy(((char *)&intValue), char_buf, typeSize);
if (NULL == (jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cInt, intValueMid, intValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case sizeof(jlong): {
jlong longValue;
memcpy(((char *)&longValue), char_buf, typeSize);
if (NULL ==
(jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cLong, longValueMid, longValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
default:
H5_BAD_ARGUMENT_ERROR(ENVONLY,
"translate_atomic_rbuf: no matching JNI type for integer type");
}
break;
} /* H5T_INTEGER */
case H5T_FLOAT: {
/* Convert each element to a list */
switch (typeSize) {
case sizeof(jfloat): {
jfloat floatValue;
memcpy(((char *)&floatValue), char_buf, typeSize);
if (NULL == (jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cFloat, floatValueMid,
(double)floatValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
case sizeof(jdouble): {
jdouble doubleValue;
memcpy(((char *)&doubleValue), char_buf, typeSize);
if (NULL == (jobj = ENVPTR->CallStaticObjectMethod(ENVONLY, cDouble, doubleValueMid,
doubleValue)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
break;
}
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY, "translate_atomic_rbuf: no matching JNI type for floating-point type");
}
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;
jsize byteArraySize = (jsize)typeSize;
if (typeSize != (size_t)byteArraySize)
H5_JNI_FATAL_ERROR(ENVONLY, "translate_atomic_rbuf: overflow of byteArraySize");
if (NULL == (jobj = ENVPTR->NewByteArray(ENVONLY, byteArraySize)))
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
PIN_BYTE_ARRAY(ENVONLY, (jbyteArray)jobj, barray, &bb,
"translate_atomic_rbuf reference: byte array not pinned");
memcpy(barray, ((jbyte *)raw_buf), typeSize);
if (barray)
UNPIN_BYTE_ARRAY(ENVONLY, (jbyteArray)jobj, barray, jobj ? 0 : JNI_ABORT);
break;
} /* H5T_REFERENCE */
case H5T_STRING: {
htri_t is_variable = 0;
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Convert each element */
if (is_variable) {
char **var_str_buf = (char **)raw_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");
}
}
else {
if (NULL == (jobj = ENVPTR->NewStringUTF(ENVONLY, char_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");
}
}
break;
} /* H5T_STRING */
case H5T_COMPLEX: {
H5T_class_t base_class;
size_t base_size, typeCount;
void *objBuf = NULL;
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(base_size = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if ((base_class = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
typeCount = typeSize / base_size;
if (NULL == (objBuf = malloc(typeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer");
memcpy((char *)objBuf, char_buf, typeSize);
/* 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");
translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf, typeSize);
jobj = jList;
if (objBuf)
free(objBuf);
break;
}
case H5T_TIME:
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
H5_UNIMPLEMENTED(ENVONLY, "translate_atomic_rbuf: invalid class type");
break;
} /* switch(type_class) */
done:
/* The base type derived from a VLEN/ARRAY/COMPLEX memory type, or the member type of
* a COMPOUND that has not been closed by the loop above, is owned by this call. */
if (memb >= 0)
H5Tclose(memb);
/* Release the class references so a deep recursion (a compound read calls this helper
* once per member per element) does not hold one set per level until the JNI call ends. */
if (arrCList)
ENVPTR->DeleteLocalRef(ENVONLY, arrCList);
if (cByte)
ENVPTR->DeleteLocalRef(ENVONLY, cByte);
if (cShort)
ENVPTR->DeleteLocalRef(ENVONLY, cShort);
if (cInt)
ENVPTR->DeleteLocalRef(ENVONLY, cInt);
if (cLong)
ENVPTR->DeleteLocalRef(ENVONLY, cLong);
if (cFloat)
ENVPTR->DeleteLocalRef(ENVONLY, cFloat);
if (cDouble)
ENVPTR->DeleteLocalRef(ENVONLY, cDouble);
return jobj;
}
void
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;
size_t vlSize;
size_t i;
size_t typeSize;
// raw_buf is normally bytes except when used for variable length strings
char *char_buf = (char *)raw_buf;
/* retrieve the java.util.ArrayList interface class */
jclass arrCList = ENVPTR->FindClass(ENVONLY, "java/util/ArrayList");
/* retrieve the toArray method */
jmethodID mToArray = ENVPTR->GetMethodID(ENVONLY, arrCList, "toArray", "()[Ljava/lang/Object;");
/* Cache class types */
jclass cByte = ENVPTR->FindClass(ENVONLY, "java/lang/Byte");
jclass cShort = ENVPTR->FindClass(ENVONLY, "java/lang/Short");
jclass cInt = ENVPTR->FindClass(ENVONLY, "java/lang/Integer");
jclass cLong = ENVPTR->FindClass(ENVONLY, "java/lang/Long");
jclass cFloat = ENVPTR->FindClass(ENVONLY, "java/lang/Float");
jclass cDouble = ENVPTR->FindClass(ENVONLY, "java/lang/Double");
jmethodID byteValueMid = ENVPTR->GetMethodID(ENVONLY, cByte, "byteValue", "()B");
jmethodID shortValueMid = ENVPTR->GetMethodID(ENVONLY, cShort, "shortValue", "()S");
jmethodID intValueMid = ENVPTR->GetMethodID(ENVONLY, cInt, "intValue", "()I");
jmethodID longValueMid = ENVPTR->GetMethodID(ENVONLY, cLong, "longValue", "()J");
jmethodID floatValueMid = ENVPTR->GetMethodID(ENVONLY, cFloat, "floatValue", "()F");
jmethodID doubleValueMid = ENVPTR->GetMethodID(ENVONLY, cDouble, "doubleValue", "()D");
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)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class((hid_t)memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
/* 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, 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: {
/* Convert each compound element */
int nmembs = H5Tget_nmembers(mem_type_id);
/* invoke the toArray method */
if (mToArray == NULL)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
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(
ENVONLY, "translate_atomic_wbuf: number of elements not equal to number of members");
/* Convert each compound object to an element */
for (i = 0; i < (size_t)nmembs; i++) {
H5T_class_t memb_vlClass;
size_t memb_vlSize;
size_t memb_offset;
if ((memb = H5Tget_member_type(mem_type_id, (unsigned int)i)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
memb_offset = H5Tget_member_offset(mem_type_id, (unsigned int)i);
if ((memb_vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(memb_vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
jobject arr_obj = ENVPTR->GetObjectArrayElement(ENVONLY, array, (jsize)i);
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);
memb = H5I_INVALID_HID;
}
ENVPTR->DeleteLocalRef(ENVONLY, array);
break;
} /* H5T_COMPOUND */
case H5T_ARRAY: {
void *objBuf = NULL;
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
/* Convert each array element */
/* invoke the toArray method */
if (mToArray == NULL)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
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");
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, (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_INTEGER: {
/* Convert each element */
switch (typeSize) {
case sizeof(jbyte): {
jbyte byteValue = ENVPTR->CallByteMethod(ENVONLY, in_obj, byteValueMid);
memcpy(char_buf, ((char *)&byteValue), typeSize);
break;
}
case sizeof(jshort): {
jshort shortValue = ENVPTR->CallShortMethod(ENVONLY, in_obj, shortValueMid);
memcpy(char_buf, ((char *)&shortValue), typeSize);
break;
}
case sizeof(jint): {
jint intValue = ENVPTR->CallIntMethod(ENVONLY, in_obj, intValueMid);
memcpy(char_buf, ((char *)&intValue), typeSize);
break;
}
case sizeof(jlong): {
jlong longValue = ENVPTR->CallLongMethod(ENVONLY, in_obj, longValueMid);
memcpy(char_buf, ((char *)&longValue), typeSize);
break;
}
default:
H5_BAD_ARGUMENT_ERROR(ENVONLY,
"translate_atomic_wbuf: no matching JNI type for integer type");
}
break;
} /* H5T_INTEGER */
case H5T_FLOAT: {
/* Convert each element */
switch (typeSize) {
case sizeof(jfloat): {
jfloat floatValue = ENVPTR->CallFloatMethod(ENVONLY, in_obj, floatValueMid);
memcpy(char_buf, ((char *)&floatValue), typeSize);
break;
}
case sizeof(jdouble): {
jdouble doubleValue = ENVPTR->CallDoubleMethod(ENVONLY, in_obj, doubleValueMid);
memcpy(char_buf, ((char *)&doubleValue), typeSize);
break;
}
default:
H5_BAD_ARGUMENT_ERROR(
ENVONLY, "translate_atomic_wbuf: no matching JNI type for floating-point type");
}
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);
ENVPTR->ReleaseByteArrayElements(ENVONLY, in_obj, barray, 0);
break;
} /* H5T_REFERENCE */
case H5T_STRING: {
htri_t is_variable = 0;
if ((is_variable = H5Tis_variable_str(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Convert each pointer element */
jsize length;
const char *utf8 = NULL;
memset(char_buf, 0, typeSize);
if (NULL != in_obj) {
PIN_JAVA_STRING(ENVONLY, in_obj, utf8, NULL, "translate_atomic_wbuf jobj not pinned");
length = ENVPTR->GetStringUTFLength(ENVONLY, in_obj);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
if (is_variable) {
char *new_buf = (char *)calloc(1, (size_t)(length + 1));
memcpy(((char *)new_buf), utf8, (size_t)length);
memcpy(char_buf, &new_buf, typeSize);
}
else {
memcpy(char_buf, utf8, (size_t)length);
}
UNPIN_JAVA_STRING(ENVONLY, in_obj, utf8);
utf8 = NULL;
}
break;
} /* H5T_STRING */
case H5T_COMPLEX: {
H5T_class_t base_class;
size_t base_size;
void *objBuf = NULL;
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(base_size = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if ((base_class = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* Convert each array element - invoke the toArray method */
if (mToArray == NULL)
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
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");
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,
(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:
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
H5_UNIMPLEMENTED(ENVONLY, "translate_atomic_wbuf: invalid class type");
break;
} /* switch(type_class) */
done:
/* The base type derived from a VLEN/ARRAY/COMPLEX memory type, or the member type of
* a COMPOUND that has not been closed by the loop above, is owned by this call. */
if (memb >= 0)
H5Tclose(memb);
/* Release the class references so a deep recursion does not hold one set per level. */
if (arrCList)
ENVPTR->DeleteLocalRef(ENVONLY, arrCList);
if (cByte)
ENVPTR->DeleteLocalRef(ENVONLY, cByte);
if (cShort)
ENVPTR->DeleteLocalRef(ENVONLY, cShort);
if (cInt)
ENVPTR->DeleteLocalRef(ENVONLY, cInt);
if (cLong)
ENVPTR->DeleteLocalRef(ENVONLY, cLong);
if (cFloat)
ENVPTR->DeleteLocalRef(ENVONLY, cFloat);
if (cDouble)
ENVPTR->DeleteLocalRef(ENVONLY, cDouble);
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, size_t buf_size)
{
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;
size_t typeSize;
// raw_buf is normally bytes except when used for variable length strings
char *char_buf = (char *)raw_buf;
/* 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");
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
/* 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: {
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
for (i = 0; i < (size_t)count; i++) {
hvl_t vl_elem;
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");
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,
(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);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
}
break;
} /* H5T_VLEN */
case H5T_COMPOUND: {
/* Convert each compound element to a fresh ArrayList of its members. */
for (i = 0; i < (size_t)count; i++) {
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);
/* 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;
size_t memb_offset;
if ((memb = H5Tget_member_type(mem_type_id, (unsigned int)x)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
memb_offset = H5Tget_member_offset(mem_type_id, (unsigned int)x);
if ((memb_vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
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, memb_vlSize);
if (jobj) {
ENVPTR->CallBooleanMethod(ENVONLY, jList, arrAddMethod, (jobject)jobj);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
ENVPTR->DeleteLocalRef(ENVONLY, jobj);
}
H5Tclose(memb);
memb = H5I_INVALID_HID;
}
if (retIsList)
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
else
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
}
break;
} /* H5T_COMPOUND */
case H5T_ARRAY: {
void *objBuf = NULL;
size_t typeCount;
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
typeCount = typeSize / vlSize;
if (NULL == (objBuf = malloc(typeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_rbuf: failed to allocate buffer");
/* Convert each element to a fresh list */
for (i = 0; i < (size_t)count; i++) {
/* 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 (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, typeSize);
if (retIsList)
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
else
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
}
if (objBuf)
free(objBuf);
break;
} /* H5T_ARRAY */
case H5T_ENUM:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_INTEGER:
case H5T_FLOAT:
case H5T_REFERENCE:
case H5T_STRING: {
/* Convert each element to a list */
for (i = 0; i < (size_t)count; i++) {
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 (retIsList)
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, (jobject)jobj);
else
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, (jobject)jobj);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
ENVPTR->DeleteLocalRef(ENVONLY, jobj);
}
}
break;
}
case H5T_COMPLEX: {
H5T_class_t base_class;
size_t base_size, typeCount;
void *objBuf = NULL;
if (!(typeSize = H5Tget_size(mem_type_id)))
H5_LIBRARY_ERROR(ENVONLY);
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(base_size = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if ((base_class = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
typeCount = typeSize / base_size;
if (NULL == (objBuf = malloc(typeSize)))
H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer");
/* Convert each element to a fresh list of 2 floating-point elements */
for (i = 0; i < (size_t)count; i++) {
/* 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 (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, typeSize);
if (retIsList)
ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList);
else
ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList);
CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
}
if (objBuf)
free(objBuf);
break;
}
case H5T_TIME:
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
H5_UNIMPLEMENTED(ENVONLY, "translate_rbuf: invalid class type");
break;
} /* switch(type_class) */
done:
/* The base type derived from a VLEN/ARRAY/COMPLEX memory type, or the member type of
* a COMPOUND that has not been closed by the loop above, is owned by this call. */
if (memb >= 0)
H5Tclose(memb);
if (arrCList)
ENVPTR->DeleteLocalRef(ENVONLY, arrCList);
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, size_t buf_size)
{
hid_t memb = H5I_INVALID_HID;
jobjectArray jList = NULL;
jobject jobj = NULL;
H5T_class_t vlClass;
size_t vlSize;
size_t i, x;
size_t typeSize;
// raw_buf is normally bytes except when used for variable length strings
char *char_buf = (char *)raw_buf;
/* retrieve the java.util.ArrayList interface class */
jclass arrCList = ENVPTR->FindClass(ENVONLY, "java/util/ArrayList");
/* retrieve the toArray method */
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: {
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class((hid_t)memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
/* Convert each list to a vlen element */
for (i = 0; i < (size_t)count; i++) {
hvl_t vl_elem;
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);
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");
vl_elem.len = (size_t)jnelmts;
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,
(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;
} /* H5T_VLEN */
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))) {
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);
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(
ENVONLY, "translate_wbuf: number of elements not equal to number of members");
/* Convert each compound object to an element */
for (x = 0; x < (size_t)nmembs; x++) {
H5T_class_t memb_vlClass;
size_t memb_vlSize;
size_t memb_offset;
if ((memb = H5Tget_member_type(mem_type_id, (unsigned int)x)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
memb_offset = H5Tget_member_offset(mem_type_id, (unsigned int)x);
if ((memb_vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(memb_vlSize = H5Tget_size(memb)))
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, memb_vlSize);
ENVPTR->DeleteLocalRef(ENVONLY, arr_obj);
H5Tclose(memb);
memb = H5I_INVALID_HID;
}
ENVPTR->DeleteLocalRef(ENVONLY, array);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
} /* end for (i = 0; i < count; i++) */
break;
} /* H5T_COMPOUND */
case H5T_ARRAY: {
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if ((vlClass = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(vlSize = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
/* 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))) {
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);
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, vlSize * (size_t)jnelmts);
ENVPTR->DeleteLocalRef(ENVONLY, array);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
} /* end for (i = 0; i < count; i++) */
break;
} /* H5T_ARRAY */
case H5T_ENUM:
case H5T_BITFIELD:
case H5T_OPAQUE:
case H5T_INTEGER:
case H5T_FLOAT:
case H5T_REFERENCE:
case H5T_STRING: {
/* Convert each list to an array element */
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);
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;
}
case H5T_COMPLEX: {
H5T_class_t base_class;
size_t base_size;
if ((memb = H5Tget_super(mem_type_id)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
if (!(base_size = H5Tget_size(memb)))
H5_LIBRARY_ERROR(ENVONLY);
if ((base_class = H5Tget_class(memb)) < 0)
H5_LIBRARY_ERROR(ENVONLY);
/* 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))) {
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);
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, base_size * (size_t)jnelmts);
ENVPTR->DeleteLocalRef(ENVONLY, array);
ENVPTR->DeleteLocalRef(ENVONLY, jList);
} /* end for (i = 0; i < count; i++) */
break;
}
case H5T_TIME:
case H5T_NO_CLASS:
case H5T_NCLASSES:
default:
H5_UNIMPLEMENTED(ENVONLY, "translate_wbuf: invalid class type");
break;
} /* switch(type_class) */
done:
/* The base type derived from a VLEN/ARRAY/COMPLEX memory type, or the member type of
* a COMPOUND that has not been closed by the loop above, is owned by this call. */
if (memb >= 0)
H5Tclose(memb);
if (arrCList)
ENVPTR->DeleteLocalRef(ENVONLY, arrCList);
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)) < 0)
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