From af162e955f8a0875ffc7d20872d0e9efbbd5fea3 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Mon, 11 Mar 2024 00:10:08 -0500 Subject: [PATCH] Implement ID creation optimization for container datatype conversions Makes the datatype conversion context object available during both the initialization and conversion processes for a datatype conversion function, allowing the compound, variable-length and array datatype conversion functions to avoid creating IDs for the datatypes when they aren't necessary Adds internal H5CX_pushed routine to determine if an API context is available to retrieve values from Also adds error checking to several places in H5T.c and H5Tconv.c where the code had previously assumed object close operations would succeed --- src/H5CX.c | 22 ++ src/H5CXprivate.h | 1 + src/H5T.c | 164 ++++++++----- src/H5Tconv.c | 584 +++++++++++++++++++++++++++------------------- src/H5Tpkg.h | 28 ++- 5 files changed, 494 insertions(+), 305 deletions(-) diff --git a/src/H5CX.c b/src/H5CX.c index c46c58af35e..0c6c8733703 100644 --- a/src/H5CX.c +++ b/src/H5CX.c @@ -759,6 +759,28 @@ H5CX__get_context(void) } /* end H5CX__get_context() */ #endif /* H5_HAVE_THREADSAFE */ +/*------------------------------------------------------------------------- + * Function: H5CX_pushed + * + * Purpose: Returns whether or not an API context has been pushed. + * + * Return: true/false + * + *------------------------------------------------------------------------- + */ +bool +H5CX_pushed(void) +{ + H5CX_node_t **head = NULL; /* Pointer to head of API context list */ + + FUNC_ENTER_NOAPI_NOERR + + head = H5CX_get_my_context(); /* Get the pointer to the head of the API context, for this thread */ + assert(head); + + FUNC_LEAVE_NOAPI(*head != NULL); +} + /*------------------------------------------------------------------------- * Function: H5CX__push_common * diff --git a/src/H5CXprivate.h b/src/H5CXprivate.h index 76812ee55ef..2a49d9ef031 100644 --- a/src/H5CXprivate.h +++ b/src/H5CXprivate.h @@ -60,6 +60,7 @@ typedef struct H5CX_state_t { H5_DLL herr_t H5CX_push(void); H5_DLL herr_t H5CX_pop(bool update_dxpl_props); #endif /* H5private_H */ +H5_DLL bool H5CX_pushed(void); H5_DLL void H5CX_push_special(void); H5_DLL bool H5CX_is_def_dxpl(void); diff --git a/src/H5T.c b/src/H5T.c index bd4d945293c..7d3db702a84 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -2495,6 +2495,17 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con } /* end if */ } /* end if */ else { + H5T_conv_ctx_t tmp_ctx = {0}; + + /* + * Get the datatype conversion exception callback structure. + * Note that we have to first check if an API context has been + * pushed, since we could have arrived here during library + * initialization of the H5T package. + */ + if (!conv->is_app && H5CX_pushed() && (H5CX_get_dt_conv_cb(&tmp_ctx.u.init.cb_struct) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* Add function to end of soft list */ if ((size_t)H5T_g.nsoft >= H5T_g.asoft) { size_t na = MAX(32, 2 * H5T_g.asoft); @@ -2542,19 +2553,27 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con "unable to register ID for destination datatype"); if ((conv->u.app_func)(tmp_sid, tmp_did, &cdata, 0, 0, 0, NULL, NULL, H5CX_get_dxpl()) < 0) { - H5I_dec_ref(tmp_sid); - H5I_dec_ref(tmp_did); + if (H5I_dec_ref(tmp_sid) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, + "unable to decrement reference count on temporary ID"); + if (H5I_dec_ref(tmp_did) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, + "unable to decrement reference count on temporary ID"); tmp_sid = tmp_did = H5I_INVALID_HID; tmp_stype = tmp_dtype = NULL; - H5E_clear_stack(NULL); + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack"); continue; } /* end if */ } /* end if */ - else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &cdata, NULL, 0, 0, 0, NULL, NULL) < 0) { - H5T_close(tmp_stype); - H5T_close(tmp_dtype); + else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &cdata, &tmp_ctx, 0, 0, 0, NULL, NULL) < 0) { + if (H5T_close(tmp_stype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close temporary datatype"); + if (H5T_close(tmp_dtype) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close temporary datatype"); tmp_stype = tmp_dtype = NULL; - H5E_clear_stack(NULL); + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack"); continue; } /* end if */ @@ -2599,8 +2618,12 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con (size_t)old_path->conv.u.lib_func, old_path->name); #endif } /* end if */ - (void)H5T_close_real(old_path->src); - (void)H5T_close_real(old_path->dst); + + if (H5T_close_real(old_path->src) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); + if (H5T_close_real(old_path->dst) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); + old_path = H5FL_FREE(H5T_path_t, old_path); /* Release temporary atoms */ @@ -2628,17 +2651,18 @@ H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_con } /* We don't care about any failures during the freeing process */ - H5E_clear_stack(NULL); + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to clear current error stack"); } /* end for */ } /* end else */ done: if (ret_value < 0) { if (new_path) { - if (new_path->src) - (void)H5T_close_real(new_path->src); - if (new_path->dst) - (void)H5T_close_real(new_path->dst); + if (new_path->src && (H5T_close_real(new_path->src) < 0)) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); + if (new_path->dst && (H5T_close_real(new_path->dst) < 0)) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); new_path = H5FL_FREE(H5T_path_t, new_path); } /* end if */ } /* end if */ @@ -3957,14 +3981,16 @@ H5T__free(H5T_t *dt) /* Don't free locked datatypes */ if (H5T_STATE_IMMUTABLE == dt->shared->state) - HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close immutable datatype"); /* Close the datatype */ switch (dt->shared->type) { case H5T_COMPOUND: for (i = 0; i < dt->shared->u.compnd.nmembs; i++) { dt->shared->u.compnd.memb[i].name = (char *)H5MM_xfree(dt->shared->u.compnd.memb[i].name); - (void)H5T_close_real(dt->shared->u.compnd.memb[i].type); + if (H5T_close_real(dt->shared->u.compnd.memb[i].type) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, + "unable to close datatype for compound member"); } dt->shared->u.compnd.memb = (H5T_cmemb_t *)H5MM_xfree(dt->shared->u.compnd.memb); dt->shared->u.compnd.nmembs = 0; @@ -4252,7 +4278,8 @@ H5T__set_size(H5T_t *dt, size_t size) /* Get a copy of unsigned char type as the base/parent type */ if (NULL == (base = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype"); - dt->shared->parent = H5T_copy(base, H5T_COPY_ALL); + if (NULL == (dt->shared->parent = H5T_copy(base, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy base datatype"); /* change this datatype into a VL string */ dt->shared->type = H5T_VLEN; @@ -4920,19 +4947,20 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst) static H5T_path_t * H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv) { - int lt, rt; /* left and right edges */ - int md; /* middle */ - int cmp; /* comparison result */ - int old_npaths; /* Previous number of paths in table */ - H5T_path_t *table = NULL; /* path existing in the table */ - H5T_path_t *path = NULL; /* new path */ - H5T_t *tmp_stype = NULL; /* temporary source datatype */ - H5T_t *tmp_dtype = NULL; /* temporary destination datatype */ - hid_t src_id = H5I_INVALID_HID; /* source datatype identifier */ - hid_t dst_id = H5I_INVALID_HID; /* destination datatype identifier */ - int i; /* counter */ - int nprint = 0; /* lines of output printed */ - H5T_path_t *ret_value = NULL; /* Return value */ + H5T_conv_ctx_t tmp_ctx = {0}; /* temporary conversion context object */ + int lt, rt; /* left and right edges */ + int md; /* middle */ + int cmp; /* comparison result */ + int old_npaths; /* Previous number of paths in table */ + H5T_path_t *table = NULL; /* path existing in the table */ + H5T_path_t *path = NULL; /* new path */ + H5T_t *tmp_stype = NULL; /* temporary source datatype */ + H5T_t *tmp_dtype = NULL; /* temporary destination datatype */ + hid_t src_id = H5I_INVALID_HID; /* source datatype identifier */ + hid_t dst_id = H5I_INVALID_HID; /* destination datatype identifier */ + int i; /* counter */ + int nprint = 0; /* lines of output printed */ + H5T_path_t *ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE @@ -4942,6 +4970,15 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co assert(dst); assert(dst->shared); + /* + * Get the datatype conversion exception callback structure. + * Note that we have to first check if an API context has been + * pushed, since we could have arrived here during library + * initialization of the H5T package. + */ + if (H5CX_pushed() && (H5CX_get_dt_conv_cb(&tmp_ctx.u.init.cb_struct) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "unable to get conversion exception callback"); + /* * Make sure the first entry in the table is the no-op conversion path. */ @@ -4957,13 +4994,15 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co H5T_g.path[0]->conv.is_app = false; H5T_g.path[0]->conv.u.lib_func = H5T__conv_noop; H5T_g.path[0]->cdata.command = H5T_CONV_INIT; - if (H5T__conv_noop(NULL, NULL, &(H5T_g.path[0]->cdata), NULL, 0, 0, 0, NULL, NULL) < 0) { + if (H5T__conv_noop(NULL, NULL, &(H5T_g.path[0]->cdata), &tmp_ctx, 0, 0, 0, NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) fprintf(H5DEBUG(T), "H5T: unable to initialize no-op conversion function (ignored)\n"); #endif - H5E_clear_stack(NULL); /*ignore the error*/ - } /* end if */ + /* Ignore any errors from the conversion function */ + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to clear current error stack"); + } /* end if */ H5T_g.path[0]->is_noop = true; H5T_g.npaths = 1; } /* end if */ @@ -5056,7 +5095,7 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co if ((conv->u.app_func)(src_id, dst_id, &(path->cdata), 0, 0, 0, NULL, NULL, H5CX_get_dxpl()) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function"); } /* end if */ - else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), NULL, 0, 0, 0, NULL, NULL) < 0) + else if ((conv->u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), &tmp_ctx, 0, 0, 0, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function"); if (src_id >= 0) { @@ -5122,14 +5161,18 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co if ((H5T_g.soft[i].conv.u.app_func)(src_id, dst_id, &(path->cdata), 0, 0, 0, NULL, NULL, H5CX_get_dxpl()) < 0) { memset(&(path->cdata), 0, sizeof(H5T_cdata_t)); - H5E_clear_stack(NULL); /*ignore the error*/ + /*ignore the error*/ + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to clear current error stack"); path_init_error = true; } /* end if */ } /* end if */ - else if ((H5T_g.soft[i].conv.u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), NULL, 0, 0, 0, NULL, - NULL) < 0) { + else if ((H5T_g.soft[i].conv.u.lib_func)(tmp_stype, tmp_dtype, &(path->cdata), &tmp_ctx, 0, 0, 0, + NULL, NULL) < 0) { memset(&(path->cdata), 0, sizeof(H5T_cdata_t)); - H5E_clear_stack(NULL); /*ignore the error*/ + /*ignore the error*/ + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to clear current error stack"); path_init_error = true; } /* end if */ @@ -5203,21 +5246,25 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co fprintf(H5DEBUG(T), "H5T: conversion function 0x%016zx free failed for %s (ignored)\n", (size_t)path->conv.u.app_func, path->name); #endif - H5E_clear_stack(NULL); /*ignore the failure*/ - } /* end if */ - } /* end if */ + /*ignore the failure*/ + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to clear current error stack"); + } /* end if */ + } /* end if */ else if ((table->conv.u.lib_func)(NULL, NULL, &(table->cdata), NULL, 0, 0, 0, NULL, NULL) < 0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) fprintf(H5DEBUG(T), "H5T: conversion function 0x%016zx free failed for %s (ignored)\n", (size_t)path->conv.u.lib_func, path->name); #endif - H5E_clear_stack(NULL); /*ignore the failure*/ - } /* end if */ - if (table->src) - (void)H5T_close_real(table->src); - if (table->dst) - (void)H5T_close_real(table->dst); + /*ignore the failure*/ + if (H5E_clear_stack(NULL) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to clear current error stack"); + } /* end if */ + if (table->src && (H5T_close_real(table->src) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype"); + if (table->dst && (H5T_close_real(table->dst) < 0)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype"); table = H5FL_FREE(H5T_path_t, table); table = path; H5T_g.path[md] = path; @@ -5254,10 +5301,10 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co done: if (!ret_value && path && path != table) { - if (path->src) - (void)H5T_close_real(path->src); - if (path->dst) - (void)H5T_close_real(path->dst); + if (path->src && (H5T_close_real(path->src) < 0)) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype"); + if (path->dst && (H5T_close_real(path->dst) < 0)) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close datatype"); path = H5FL_FREE(H5T_path_t, path); } /* end if */ @@ -5538,7 +5585,7 @@ H5T_convert(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, size_t nelmts, #endif /* Get the datatype conversion exception callback structure from the API context */ - if (H5CX_get_dt_conv_cb(&conv_ctx.cb_struct) < 0) + if (H5CX_get_dt_conv_cb(&conv_ctx.u.conv.cb_struct) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); /* @@ -5547,7 +5594,7 @@ H5T_convert(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, size_t nelmts, * those as appropriate. Also grab the DXPL if necessary so we can pass * that to the app conversion function. */ - if (tpath->conv.is_app || conv_ctx.cb_struct.func) { + if (tpath->conv.is_app || conv_ctx.u.conv.cb_struct.func) { if ((src_type_id = H5I_register(H5I_DATATYPE, src_type, false)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register ID for source datatype"); if ((dst_type_id = H5I_register(H5I_DATATYPE, dst_type, false)) < 0) @@ -5555,10 +5602,10 @@ H5T_convert(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, size_t nelmts, "unable to register ID for destination datatype"); if (tpath->conv.is_app) - conv_ctx.dxpl_id = H5CX_get_dxpl(); + conv_ctx.u.conv.dxpl_id = H5CX_get_dxpl(); } - conv_ctx.src_type_id = src_type_id; - conv_ctx.dst_type_id = dst_type_id; + conv_ctx.u.conv.src_type_id = src_type_id; + conv_ctx.u.conv.dst_type_id = dst_type_id; if (H5T_convert_with_ctx(tpath, src_type, dst_type, &conv_ctx, nelmts, buf_stride, bkg_stride, buf, bkg) < 0) @@ -5619,8 +5666,9 @@ H5T_convert_with_ctx(H5T_path_t *tpath, H5T_t *src_type, H5T_t *dst_type, const /* Call the appropriate conversion callback */ tpath->cdata.command = H5T_CONV_CONV; if (tpath->conv.is_app) { - if ((tpath->conv.u.app_func)(conv_ctx->src_type_id, conv_ctx->dst_type_id, &(tpath->cdata), nelmts, - buf_stride, bkg_stride, buf, bkg, conv_ctx->dxpl_id) < 0) + if ((tpath->conv.u.app_func)(conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, + &(tpath->cdata), nelmts, buf_stride, bkg_stride, buf, bkg, + conv_ctx->u.conv.dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); } /* end if */ else if ((tpath->conv.u.lib_func)(src_type, dst_type, &(tpath->cdata), conv_ctx, nelmts, buf_stride, diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 554694aa79e..607b5efe37b 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -185,9 +185,9 @@ #define H5T_CONV_Xx_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) > (ST)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MAX); \ @@ -196,9 +196,9 @@ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } \ else if (*(S) < (ST)(D_MIN)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MIN); \ @@ -224,9 +224,9 @@ #define H5T_CONV_Ux_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) > (ST)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MAX); \ @@ -255,9 +255,9 @@ #define H5T_CONV_sU_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) < 0) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = 0; \ @@ -317,9 +317,9 @@ /* Called if overflow is possible */ #define H5T_CONV_uS_CORE_1(S, D, ST, DT, D_MIN, D_MAX) \ if (*(S) > (DT)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler */ \ *(D) = (DT)(D_MAX); \ @@ -380,9 +380,9 @@ #define H5T_CONV_Su_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) < 0) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = 0; \ @@ -391,9 +391,9 @@ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } \ else if (sizeof(ST) > sizeof(DT) && *(S) > (ST)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MAX); \ @@ -436,9 +436,9 @@ { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*(S) < 0) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = 0; \ @@ -468,9 +468,9 @@ { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*(S) > (ST)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MAX); \ @@ -508,9 +508,9 @@ #define H5T_CONV_Ff_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) > (ST)(D_MAX)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g); \ @@ -519,9 +519,9 @@ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } \ else if (*(S) < (ST)(D_MIN)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g); \ @@ -618,9 +618,9 @@ \ /* Check for more bits of precision in src than available in dst */ \ if ((high_bit_pos - low_bit_pos) >= dprec) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, \ + S, D, conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(*(S)); \ @@ -655,9 +655,9 @@ #define H5T_CONV_Fx_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ { \ if (*(S) > (ST)(D_MAX) || (sprec < dprec && *(S) == (ST)(D_MAX))) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MAX); \ @@ -666,9 +666,9 @@ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } \ else if (*(S) < (ST)(D_MIN)) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(D_MIN); \ @@ -677,9 +677,9 @@ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } \ else if (*(S) != (ST)((DT)(*(S)))) { \ - H5T_conv_ret_t except_ret = \ - (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->src_type_id, \ - conv_ctx->dst_type_id, S, D, conv_ctx->cb_struct.user_data); \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ if (except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ *(D) = (DT)(*(S)); \ @@ -956,7 +956,7 @@ done: /* The outer wrapper for the type conversion loop, to check for an exception handling routine */ #define H5T_CONV_LOOP_OUTER(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS, GUTS, \ STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ - if (conv_ctx->cb_struct.func) { \ + if (conv_ctx->u.conv.cb_struct.func) { \ H5T_CONV_LOOP(PRE_SALIGN_GUTS, PRE_DALIGN_GUTS, POST_SALIGN_GUTS, POST_DALIGN_GUTS, GUTS, STYPE, \ DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ } \ @@ -1071,6 +1071,7 @@ typedef struct H5T_conv_struct_t { H5T_path_t **memb_path; /*conversion path for each member */ H5T_subset_info_t subset_info; /*info related to compound subsets */ unsigned src_nmembs; /*needed by free function */ + bool need_ids; /*whether we need IDs for the datatypes */ } H5T_conv_struct_t; /* Conversion data for H5T__conv_enum() */ @@ -1796,12 +1797,12 @@ H5T__conv_b_b(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * */ if (src->shared->u.atomic.prec > dst->shared->u.atomic.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, - conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } /* end if */ if (except_ret == H5T_CONV_UNHANDLED) { @@ -1906,14 +1907,14 @@ H5T__conv_b_b(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * /*------------------------------------------------------------------------- * Function: H5T__conv_struct_free * - * Purpose: Free the private data structure used by the compound - * conversion functions. + * Purpose: Free the private data structure used by the compound + * conversion functions. * - * Return: The result of H5MM_xfree(priv) (NULL) + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ -static H5T_conv_struct_t * +static herr_t H5T__conv_struct_free(H5T_conv_struct_t *priv) { int *src2dst = priv->src2dst; @@ -1921,17 +1922,24 @@ H5T__conv_struct_free(H5T_conv_struct_t *priv) H5T_t **dst_memb = priv->dst_memb; hid_t *src_memb_id = priv->src_memb_id; hid_t *dst_memb_id = priv->dst_memb_id; + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE_NOERR for (unsigned i = 0; i < priv->src_nmembs; i++) if (src2dst[i] >= 0) { - int H5_ATTR_NDEBUG_UNUSED status; - - status = H5I_dec_ref(src_memb_id[i]); - assert(status >= 0); - status = H5I_dec_ref(dst_memb_id[src2dst[i]]); - assert(status >= 0); + if (priv->need_ids) { + if (H5I_dec_ref(src_memb_id[i]) < 0) + ret_value = FAIL; /* set return value, but keep going */ + if (H5I_dec_ref(dst_memb_id[src2dst[i]]) < 0) + ret_value = FAIL; /* set return value, but keep going */ + } + else { + if (H5T_close(src_memb[i]) < 0) + ret_value = FAIL; /* set return value, but keep going */ + if (H5T_close(dst_memb[src2dst[i]]) < 0) + ret_value = FAIL; /* set return value, but keep going */ + } } /* end if */ H5MM_xfree(src2dst); @@ -1939,9 +1947,11 @@ H5T__conv_struct_free(H5T_conv_struct_t *priv) H5MM_xfree(dst_memb); H5MM_xfree(src_memb_id); H5MM_xfree(dst_memb_id); + H5MM_xfree(priv->memb_path); + H5MM_xfree(priv); - FUNC_LEAVE_NOAPI((H5T_conv_struct_t *)H5MM_xfree(priv)) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__conv_struct_free() */ /*------------------------------------------------------------------------- @@ -1988,7 +1998,7 @@ H5T__conv_struct_free(H5T_conv_struct_t *priv) *------------------------------------------------------------------------- */ static herr_t -H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) +H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx) { H5T_conv_struct_t *priv = (H5T_conv_struct_t *)(cdata->priv); int *src2dst = NULL; @@ -2005,13 +2015,31 @@ H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) /* * Allocate private data structure and arrays. */ - if (NULL == (priv = (H5T_conv_struct_t *)(cdata->priv = H5MM_calloc(sizeof(H5T_conv_struct_t)))) || - NULL == (priv->src2dst = (int *)H5MM_malloc(src_nmembs * sizeof(int))) || - NULL == (priv->src_memb = (H5T_t **)H5MM_malloc(src_nmembs * sizeof(H5T_t *))) || - NULL == (priv->dst_memb = (H5T_t **)H5MM_malloc(dst_nmembs * sizeof(H5T_t *))) || - NULL == (priv->src_memb_id = (hid_t *)H5MM_malloc(src_nmembs * sizeof(hid_t))) || - NULL == (priv->dst_memb_id = (hid_t *)H5MM_malloc(dst_nmembs * sizeof(hid_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if (NULL == (priv = (H5T_conv_struct_t *)(cdata->priv = H5MM_calloc(sizeof(H5T_conv_struct_t))))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "couldn't allocate private conversion data"); + if (NULL == (priv->src2dst = (int *)H5MM_malloc(src_nmembs * sizeof(int)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate source to destination member mapping array"); + if (NULL == (priv->src_memb = (H5T_t **)H5MM_malloc(src_nmembs * sizeof(H5T_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate source compound member datatype array"); + if (NULL == (priv->dst_memb = (H5T_t **)H5MM_malloc(dst_nmembs * sizeof(H5T_t *)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate destination compound member datatype array"); + + priv->need_ids = (cdata->command == H5T_CONV_INIT && conv_ctx->u.init.cb_struct.func) || + (cdata->command == H5T_CONV_CONV && conv_ctx->u.conv.cb_struct.func); + + /* Only create IDs for compound member datatypes if we need to */ + if (priv->need_ids) { + if (NULL == (priv->src_memb_id = (hid_t *)H5MM_malloc(src_nmembs * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate source compound member datatype ID array"); + if (NULL == (priv->dst_memb_id = (hid_t *)H5MM_malloc(dst_nmembs * sizeof(hid_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, + "couldn't allocate destination compound member datatype ID array"); + } + src2dst = priv->src2dst; priv->src_nmembs = src_nmembs; @@ -2030,8 +2058,7 @@ H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) * Build a mapping from source member number to destination member * number. If some source member is not a destination member then that * mapping element will be negative. Also create atoms for each - * source and destination member datatype so we can look up the - * member datatype conversion functions later. + * source and destination member datatype if necessary. */ for (i = 0; i < src_nmembs; i++) { src2dst[i] = -1; @@ -2050,20 +2077,24 @@ H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) "can't copy source compound member datatype"); priv->src_memb[i] = type; - if ((tid = H5I_register(H5I_DATATYPE, type, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "can't register ID for source compound member datatype"); - priv->src_memb_id[i] = tid; + if (priv->need_ids) { + if ((tid = H5I_register(H5I_DATATYPE, type, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "can't register ID for source compound member datatype"); + priv->src_memb_id[i] = tid; + } if (NULL == (type = H5T_copy(dst->shared->u.compnd.memb[src2dst[i]].type, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy destination compound member datatype"); priv->dst_memb[src2dst[i]] = type; - if ((tid = H5I_register(H5I_DATATYPE, type, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "can't register ID for source compound member datatype"); - priv->dst_memb_id[src2dst[i]] = tid; + if (priv->need_ids) { + if ((tid = H5I_register(H5I_DATATYPE, type, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "can't register ID for source compound member datatype"); + priv->dst_memb_id[src2dst[i]] = tid; + } } /* end if */ } /* end for */ } /* end if */ @@ -2090,7 +2121,8 @@ H5T__conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) dst->shared->u.compnd.memb[src2dst[i]].type); if (NULL == (priv->memb_path[i] = tpath)) { - cdata->priv = H5T__conv_struct_free(priv); + H5T__conv_struct_free(priv); + cdata->priv = NULL; HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert member datatype"); } /* end if */ } /* end if */ @@ -2247,16 +2279,21 @@ H5T__conv_struct(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_ if (H5T_COMPOUND != dst->shared->type) HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_COMPOUND datatype"); - if (H5T__conv_struct_init(src, dst, cdata) < 0) + if (H5T__conv_struct_init(src, dst, cdata, conv_ctx) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize conversion data"); break; - case H5T_CONV_FREE: + case H5T_CONV_FREE: { /* * Free the private conversion data. */ - cdata->priv = H5T__conv_struct_free(priv); + herr_t status = H5T__conv_struct_free(priv); + cdata->priv = NULL; + if (status < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free private conversion data"); + break; + } case H5T_CONV_CONV: /* @@ -2272,7 +2309,7 @@ H5T__conv_struct(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_ /* Initialize temporary conversion context */ tmp_conv_ctx = *conv_ctx; - if (cdata->recalc && H5T__conv_struct_init(src, dst, cdata) < 0) + if (cdata->recalc && H5T__conv_struct_init(src, dst, cdata, conv_ctx) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize conversion data"); /* @@ -2323,9 +2360,11 @@ H5T__conv_struct(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_ dst_memb = dst->shared->u.compnd.memb + src2dst[u]; if (dst_memb->size <= src_memb->size) { - /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = priv->src_memb_id[u]; - tmp_conv_ctx.dst_type_id = priv->dst_memb_id[src2dst[u]]; + if (priv->need_ids) { + /* Update IDs in conversion context */ + tmp_conv_ctx.u.conv.src_type_id = priv->src_memb_id[u]; + tmp_conv_ctx.u.conv.dst_type_id = priv->dst_memb_id[src2dst[u]]; + } if (H5T_convert_with_ctx(priv->memb_path[u], priv->src_memb[u], priv->dst_memb[src2dst[u]], &tmp_conv_ctx, (size_t)1, @@ -2358,9 +2397,11 @@ H5T__conv_struct(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_ dst_memb = dst->shared->u.compnd.memb + src2dst[i]; if (dst_memb->size > src_memb->size) { - /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = priv->src_memb_id[i]; - tmp_conv_ctx.dst_type_id = priv->dst_memb_id[src2dst[i]]; + if (priv->need_ids) { + /* Update IDs in conversion context */ + tmp_conv_ctx.u.conv.src_type_id = priv->src_memb_id[i]; + tmp_conv_ctx.u.conv.dst_type_id = priv->dst_memb_id[src2dst[i]]; + } offset -= src_memb->size; if (H5T_convert_with_ctx(priv->memb_path[i], priv->src_memb[i], @@ -2485,7 +2526,7 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_COMPOUND datatype"); /* Initialize data which is relatively constant */ - if (H5T__conv_struct_init(src, dst, cdata) < 0) + if (H5T__conv_struct_init(src, dst, cdata, conv_ctx) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize conversion data"); priv = (H5T_conv_struct_t *)(cdata->priv); src2dst = priv->src2dst; @@ -2518,7 +2559,8 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ if (dst_memb->size > src_memb->size) { offset -= src_memb->size; if (dst_memb->size > src->shared->size - offset) { - cdata->priv = H5T__conv_struct_free(priv); + H5T__conv_struct_free(priv); + cdata->priv = NULL; HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion is unsupported by this function"); } /* end if */ @@ -2527,12 +2569,17 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ } /* end if */ break; - case H5T_CONV_FREE: + case H5T_CONV_FREE: { /* * Free the private conversion data. */ - cdata->priv = H5T__conv_struct_free((H5T_conv_struct_t *)(cdata->priv)); + herr_t status = H5T__conv_struct_free((H5T_conv_struct_t *)(cdata->priv)); + cdata->priv = NULL; + if (status < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free private conversion data"); + break; + } case H5T_CONV_CONV: /* @@ -2547,7 +2594,7 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ tmp_conv_ctx = *conv_ctx; /* Update cached data if necessary */ - if (cdata->recalc && H5T__conv_struct_init(src, dst, cdata) < 0) + if (cdata->recalc && H5T__conv_struct_init(src, dst, cdata, conv_ctx) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize conversion data"); priv = (H5T_conv_struct_t *)(cdata->priv); assert(priv); @@ -2608,9 +2655,11 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ dst_memb = dst->shared->u.compnd.memb + src2dst[u]; if (dst_memb->size <= src_memb->size) { - /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = priv->src_memb_id[u]; - tmp_conv_ctx.dst_type_id = priv->dst_memb_id[src2dst[u]]; + if (priv->need_ids) { + /* Update IDs in conversion context */ + tmp_conv_ctx.u.conv.src_type_id = priv->src_memb_id[u]; + tmp_conv_ctx.u.conv.dst_type_id = priv->dst_memb_id[src2dst[u]]; + } xbuf = buf + src_memb->offset; xbkg = bkg + dst_memb->offset; @@ -2649,9 +2698,11 @@ H5T__conv_struct_opt(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ dst_memb = dst->shared->u.compnd.memb + src2dst[i]; if (dst_memb->size > src_memb->size) { - /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = priv->src_memb_id[i]; - tmp_conv_ctx.dst_type_id = priv->dst_memb_id[src2dst[i]]; + if (priv->need_ids) { + /* Update IDs in conversion context */ + tmp_conv_ctx.u.conv.src_type_id = priv->src_memb_id[i]; + tmp_conv_ctx.u.conv.dst_type_id = priv->dst_memb_id[src2dst[i]]; + } offset -= src_memb->size; xbuf = buf + offset; @@ -2949,10 +3000,10 @@ H5T__conv_enum(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t /*overflow*/ except_ret = H5T_CONV_UNHANDLED; /*If user's exception handler is present, use it*/ - if (conv_ctx->cb_struct.func) - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, s, d, - conv_ctx->cb_struct.user_data); + if (conv_ctx->u.conv.cb_struct.func) + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, s, d, conv_ctx->u.conv.cb_struct.user_data); if (except_ret == H5T_CONV_UNHANDLED) memset(d, 0xff, dst->shared->size); @@ -2987,10 +3038,10 @@ H5T__conv_enum(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t if (lt >= rt) { except_ret = H5T_CONV_UNHANDLED; /*If user's exception handler is present, use it*/ - if (conv_ctx->cb_struct.func) - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, s, d, - conv_ctx->cb_struct.user_data); + if (conv_ctx->u.conv.cb_struct.func) + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, s, d, conv_ctx->u.conv.cb_struct.user_data); if (except_ret == H5T_CONV_UNHANDLED) memset(d, 0xff, dst->shared->size); @@ -3147,6 +3198,7 @@ H5T__conv_vlen(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t void *tmp_buf = NULL; /*temporary background buffer */ size_t tmp_buf_size = 0; /*size of temporary bkg buffer */ bool nested = false; /*flag of nested VL case */ + bool need_ids = false; /*whether we need IDs for the datatypes */ size_t elmtno; /*element number counter */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3196,6 +3248,8 @@ H5T__conv_vlen(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t /* Initialize temporary conversion context */ tmp_conv_ctx = *conv_ctx; + need_ids = (conv_ctx->u.conv.cb_struct.func != NULL); + /* Initialize source & destination strides */ if (buf_stride) { assert(buf_stride >= src->shared->size); @@ -3235,10 +3289,6 @@ H5T__conv_vlen(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t if (H5T_set_loc(tsrc_cpy, src->shared->u.vlen.file, src->shared->u.vlen.loc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set datatype location"); - if ((tsrc_id = H5I_register(H5I_DATATYPE, tsrc_cpy, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "unable to register ID for source base datatype"); - if (NULL == (tdst_cpy = H5T_copy(dst->shared->parent, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy dst base type for conversion"); @@ -3247,13 +3297,18 @@ H5T__conv_vlen(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t if (H5T_set_loc(tdst_cpy, dst->shared->u.vlen.file, dst->shared->u.vlen.loc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set datatype location"); - if ((tdst_id = H5I_register(H5I_DATATYPE, tdst_cpy, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "unable to register ID for destination base datatype"); + if (need_ids) { + if ((tsrc_id = H5I_register(H5I_DATATYPE, tsrc_cpy, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for source base datatype"); + if ((tdst_id = H5I_register(H5I_DATATYPE, tdst_cpy, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for destination base datatype"); + } /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = tsrc_id; - tmp_conv_ctx.dst_type_id = tdst_id; + tmp_conv_ctx.u.conv.src_type_id = tsrc_id; + tmp_conv_ctx.u.conv.dst_type_id = tdst_id; } /* end else-if */ else noop_conv = true; @@ -3533,6 +3588,7 @@ H5T__conv_array(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t uint8_t *sp, *dp; /*source and dest traversal ptrs */ ssize_t src_delta, dst_delta; /*source & destination stride */ int direction; /*direction of traversal */ + bool need_ids = false; /*whether we need IDs for the datatypes */ void *bkg_buf = NULL; /*temporary background buffer */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3582,6 +3638,8 @@ H5T__conv_array(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t /* Initialize temporary conversion context */ tmp_conv_ctx = *conv_ctx; + need_ids = (conv_ctx->u.conv.cb_struct.func != NULL); + /* * Do we process the values from beginning to end or vice * versa? Also, how many of the elements have the source and @@ -3615,20 +3673,23 @@ H5T__conv_array(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t if (NULL == (tsrc_cpy = H5T_copy(src->shared->parent, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy src base type for conversion"); - if ((tsrc_id = H5I_register(H5I_DATATYPE, tsrc_cpy, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "unable to register ID for source base datatype"); if (NULL == (tdst_cpy = H5T_copy(dst->shared->parent, H5T_COPY_ALL))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy dst base type for conversion"); - if ((tdst_id = H5I_register(H5I_DATATYPE, tdst_cpy, false)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, - "unable to register ID for destination base datatype"); + + if (need_ids) { + if ((tsrc_id = H5I_register(H5I_DATATYPE, tsrc_cpy, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for source base datatype"); + if ((tdst_id = H5I_register(H5I_DATATYPE, tdst_cpy, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register ID for destination base datatype"); + } /* Update IDs in conversion context */ - tmp_conv_ctx.src_type_id = tsrc_id; - tmp_conv_ctx.dst_type_id = tdst_id; + tmp_conv_ctx.u.conv.src_type_id = tsrc_id; + tmp_conv_ctx.u.conv.dst_type_id = tdst_id; } /* Check if we need a background buffer for this conversion */ @@ -4066,12 +4127,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * } else if (first >= dst->shared->u.atomic.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4100,12 +4163,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * */ if (first + 1 == src->shared->u.atomic.prec) { /*overflow - source is negative*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4126,12 +4191,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * } else if (first >= dst->shared->u.atomic.prec) { /*overflow - source is positive*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) @@ -4157,12 +4224,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * */ if (first + 1 >= dst->shared->u.atomic.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4203,12 +4272,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * if (sfz >= 0 && fz + 1 >= dst->shared->u.atomic.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4244,12 +4315,14 @@ H5T__conv_i_i(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t * */ if (first + 1 >= dst->shared->u.atomic.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ H5T__reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4524,18 +4597,21 @@ H5T__conv_f_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { /* +Inf or -Inf */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); if (sign) - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); else - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4567,17 +4643,19 @@ H5T__conv_f_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx *If the exponent bits are all 1s and only the 1st bit of mantissa *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ /* +Inf or -Inf */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); if (sign) - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, src_rev, - d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); else - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, src_rev, - d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4607,12 +4685,12 @@ H5T__conv_f_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { /* NaN */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_NAN, conv_ctx->src_type_id, - conv_ctx->dst_type_id, src_rev, d, - conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NAN, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4729,12 +4807,12 @@ H5T__conv_f_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx * handler make sure the source buffer we hand it is in the * original byte order. */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, - conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -4820,13 +4898,15 @@ H5T__conv_f_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx * calling the overflow handler make sure the source * buffer we hand it is in the original byte order. */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8258,14 +8338,16 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { /* +Infinity or -Infinity */ - if (sign) { /* -Infinity */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (sign) { /* -Infinity */ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8281,14 +8363,16 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else { /* +Infinity */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + else { /* +Infinity */ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8316,14 +8400,16 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx *If the exponent bits are all 1s and only the 1st bit of mantissa *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ /* +Infinity or -Infinity */ - if (sign) { /* -Infinity */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (sign) { /* -Infinity */ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, src_rev, - d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8339,14 +8425,16 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else { /* +Infinity */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + else { /* +Infinity */ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->src_type_id, conv_ctx->dst_type_id, src_rev, - d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8368,12 +8456,12 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { /* NaN */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_NAN, conv_ctx->src_type_id, - conv_ctx->dst_type_id, src_rev, d, - conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_NAN, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8444,7 +8532,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx * If expo is less than mantissa size, the frantional value is dropped off * during conversion. Set exception type to be "truncate" */ - if ((size_t)expo < src.u.f.msize && conv_ctx->cb_struct.func) + if ((size_t)expo < src.u.f.msize && conv_ctx->u.conv.cb_struct.func) truncated = true; /* @@ -8470,14 +8558,16 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx * zero(do nothing). If user's exception handler is set, call it and * let user handle it. */ - if (sign) { /*source is negative*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (sign) { /*source is negative*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); if (except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); @@ -8491,13 +8581,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx else { /*source is positive*/ if (first >= dst.prec) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) @@ -8512,14 +8604,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx "can't handle conversion exception"); } else if (first < dst.prec) { - if (truncated && - conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (truncated && conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) @@ -8539,14 +8632,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx else if (H5T_SGN_2 == dst.u.i.sign) { /*Destination is signed*/ if (sign) { /*source is negative*/ if (first < dst.prec - 1) { - if (truncated && - conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (truncated && conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { /*If this case ignored by user handler*/ @@ -8571,13 +8665,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx /* if underflows and no callback, do nothing except turn on * the sign bit because 0x80...00 is the biggest negative value. */ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) @@ -8595,13 +8691,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx else { /*source is positive*/ if (first >= dst.prec - 1) { /*overflow*/ - if (conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) @@ -8616,14 +8714,15 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } } else if (first < dst.prec - 1) { - if (truncated && - conv_ctx->cb_struct.func) { /*If user's exception handler is present, use it*/ + if (truncated && conv_ctx->u.conv.cb_struct + .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { @@ -8942,12 +9041,12 @@ H5T__conv_i_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx /* If the bit sequence is bigger than the mantissa part, there'll be some * precision loss. Let user's handler deal with the case if it's present */ - if (conv_ctx->cb_struct.func) { + if (conv_ctx->u.conv.cb_struct.func) { H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, - conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_HANDLED) { @@ -9013,13 +9112,14 @@ H5T__conv_i_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx /* Check if the exponent is too big */ expo_max = (hsize_t)(pow(2.0, (double)dst.u.f.esize) - 1); - if (expo > expo_max) { /*overflows*/ - if (conv_ctx->cb_struct.func) { /*user's exception handler. Reverse back source order*/ + if (expo > expo_max) { /*overflows*/ + if (conv_ctx->u.conv.cb_struct + .func) { /*user's exception handler. Reverse back source order*/ H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, - conv_ctx->src_type_id, conv_ctx->dst_type_id, - src_rev, d, conv_ctx->cb_struct.user_data); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); if (except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 97e39b262eb..ddca0b35d16 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -152,17 +152,35 @@ struct H5T_stats_t { /* Context struct for information used during datatype conversions */ typedef struct H5T_conv_ctx_t { - H5T_conv_cb_t cb_struct; - hid_t dxpl_id; - hid_t src_type_id; - hid_t dst_type_id; + union { + /* + * Fields only valid during conversion function initialization + * (H5T_cmd_t H5T_CONV_INIT) + */ + struct H5T_conv_ctx_init_fields { + H5T_conv_cb_t cb_struct; + } init; + + /* + * Fields only valid during conversion function conversion + * process (H5T_cmd_t H5T_CONV_CONV) + */ + struct H5T_conv_ctx_conv_fields { + H5T_conv_cb_t cb_struct; + hid_t dxpl_id; + hid_t src_type_id; + hid_t dst_type_id; + } conv; + + /* No fields currently defined for H5T_cmd_t H5T_CONV_FREE */ + } u; } H5T_conv_ctx_t; /* Library internal datatype conversion functions are... */ typedef herr_t (*H5T_lib_conv_t)(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); -/* Conversion callbacks (library internal ones don't need DXPL) */ +/* Conversion callbacks */ typedef struct H5T_conv_func_t { bool is_app; /* Whether conversion function is registered from application */ union {