diff options
author | Robb Matzke <matzke@llnl.gov> | 1998-01-26 20:56:18 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1998-01-26 20:56:18 (GMT) |
commit | 5c6a3af39679b2bbbdaebf8f1c19edbeed7af248 (patch) | |
tree | 8c495a15af0ae785dfcb22420e197d583deef7ba | |
parent | 6cd8818b735d3c22f3a1f7cd30d52360139ed72c (diff) | |
download | hdf5-5c6a3af39679b2bbbdaebf8f1c19edbeed7af248.zip hdf5-5c6a3af39679b2bbbdaebf8f1c19edbeed7af248.tar.gz hdf5-5c6a3af39679b2bbbdaebf8f1c19edbeed7af248.tar.bz2 |
[svn-r170] Changes since 19980123
----------------------
./src/H5D.c
./src/H5T.c
./src/H5Tconv.c
./src/H5Tpkg.h
./src/H5Tprivate.h
./src/H5Tpublic.h
./test/cmpd_dset.c
Added support to turn background buffer on/off to help speed
up conversions. Currently, every type of conversion turns it
off except compound-->compound conversions which always turn
it on. In the future the compound-->compound conversions
might be more frugal.
-rw-r--r-- | src/H5D.c | 32 | ||||
-rw-r--r-- | src/H5T.c | 107 | ||||
-rw-r--r-- | src/H5Tconv.c | 300 | ||||
-rw-r--r-- | src/H5Tpkg.h | 15 | ||||
-rw-r--r-- | src/H5Tprivate.h | 2 | ||||
-rw-r--r-- | src/H5Tpublic.h | 21 | ||||
-rw-r--r-- | test/cmpd_dset.c | 45 |
7 files changed, 370 insertions, 152 deletions
@@ -837,7 +837,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ const H5P_conv_t *sconv_func = NULL; /*space conversion funcs*/ H5P_number_t numbering; /*element numbering info*/ - void *cdata = NULL; /*type conversion data */ + H5T_cdata_t *cdata = NULL; /*type conversion data */ herr_t ret_value = FAIL; FUNC_ENTER(H5D_read, FAIL); @@ -895,7 +895,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, size_t src_size = nelmts * H5T_get_size(dataset->type); size_t dst_size = nelmts * H5T_get_size(mem_type); tconv_buf = H5MM_xmalloc(MAX(src_size, dst_size)); - bkg_buf = H5MM_xmalloc (dst_size); + if (cdata->need_bkg) bkg_buf = H5MM_xmalloc (dst_size); } #endif @@ -911,15 +911,18 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, tconv_buf/*out*/)!=nelmts) { HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); } - if ((sconv_func->mgath)(buf, H5T_get_size (mem_type), mem_space, - &numbering, 0, nelmts, bkg_buf/*out*/)!=nelmts) { - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + if (H5T_BKG_YES==cdata->need_bkg) { + if ((sconv_func->mgath)(buf, H5T_get_size (mem_type), mem_space, + &numbering, 0, nelmts, + bkg_buf/*out*/)!=nelmts) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + } } /* * Perform data type conversion. */ - if ((tconv_func) (src_id, dst_id, &cdata, nelmts, tconv_buf, bkg_buf)<0) { + if ((tconv_func) (src_id, dst_id, cdata, nelmts, tconv_buf, bkg_buf)<0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); } @@ -970,7 +973,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ const H5P_conv_t *sconv_func = NULL; /*space conversion funcs*/ H5P_number_t numbering; /*element numbering info*/ - void *cdata = NULL; /*type conversion data */ + H5T_cdata_t *cdata = NULL; /*type conversion data */ herr_t ret_value = FAIL; FUNC_ENTER(H5D_write, FAIL); @@ -1028,7 +1031,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, size_t src_size = nelmts * H5T_get_size(mem_type); size_t dst_size = nelmts * H5T_get_size(dataset->type); tconv_buf = H5MM_xmalloc(MAX(src_size, dst_size)); - bkg_buf = H5MM_xmalloc (dst_size); + if (cdata->need_bkg) bkg_buf = H5MM_xmalloc (dst_size); } #endif @@ -1043,16 +1046,19 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5P_t *mem_space, &numbering, 0, nelmts, tconv_buf/*out*/)!=nelmts) { HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed"); } - if ((sconv_func->fgath)(dataset->ent.file, &(dataset->layout), - H5T_get_size (dataset->type), file_space, - &numbering, 0, nelmts, bkg_buf/*out*/)!=nelmts) { - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + if (H5T_BKG_YES==cdata->need_bkg) { + if ((sconv_func->fgath)(dataset->ent.file, &(dataset->layout), + H5T_get_size (dataset->type), file_space, + &numbering, 0, nelmts, + bkg_buf/*out*/)!=nelmts) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + } } /* * Perform data type conversion. */ - if ((tconv_func) (src_id, dst_id, &cdata, nelmts, tconv_buf, bkg_buf)<0) { + if ((tconv_func) (src_id, dst_id, cdata, nelmts, tconv_buf, bkg_buf)<0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); } @@ -2068,9 +2068,10 @@ H5Tpack(hid_t type_id) herr_t H5Tregister_hard(hid_t src_id, hid_t dst_id, H5T_conv_t func) { - H5T_t *src = NULL; - H5T_t *dst = NULL; - H5T_path_t *path = NULL; + H5T_t *src = NULL; + H5T_t *dst = NULL; + H5T_path_t *path = NULL; + intn i; FUNC_ENTER(H5Tregister_hard, FAIL); @@ -2081,16 +2082,31 @@ H5Tregister_hard(hid_t src_id, hid_t dst_id, H5T_conv_t func) NULL == (dst = H5A_object(dst_id))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); } + /* Locate or create a new conversion path */ if (NULL == (path = H5T_path_find(src, dst, TRUE))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to locate/allocate conversion path"); } + /* Initialize the hard function */ path->hard = func; + + /* + * Notify all soft functions to recalculate private data since some + * functions might cache a list of conversion functions. For instance, + * the compound type converter caches a list of conversion functions for + * the members, so adding a new function should cause the list to be + * recalculated to use the new function. + */ + for (i=0; i<H5T_npath_g; i++) { + H5T_path_g[i].cdata->recalc = TRUE; + } + + FUNC_LEAVE(SUCCEED); } - + /*------------------------------------------------------------------------- * Function: H5Tregister_soft * @@ -2114,6 +2130,7 @@ H5Tregister_soft(H5T_class_t src_cls, H5T_class_t dst_cls, H5T_conv_t func) { intn i; hid_t src_id, dst_id; + H5T_cdata_t *cdata = NULL; FUNC_ENTER(H5Tregister_soft, FAIL); @@ -2127,6 +2144,7 @@ H5Tregister_soft(H5T_class_t src_cls, H5T_class_t dst_cls, H5T_conv_t func) HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no soft conversion function specified"); } + /* Add function to end of master list */ if (H5T_nsoft_g >= H5T_asoft_g) { H5T_asoft_g = MAX(32, 2 * H5T_asoft_g); @@ -2139,9 +2157,11 @@ H5Tregister_soft(H5T_class_t src_cls, H5T_class_t dst_cls, H5T_conv_t func) H5T_nsoft_g++; /* Replace soft functions of all appropriate paths */ - for (i = 0; i < H5T_npath_g; i++) { + for (i=0; i<H5T_npath_g; i++) { H5T_path_t *path = H5T_path_g + i; - void *cdata = NULL; + if (!cdata) { + cdata = H5MM_xcalloc (1, sizeof(H5T_cdata_t)); + } /* * Type conversion functions are app-level, so we need to convert the @@ -2156,11 +2176,34 @@ H5Tregister_soft(H5T_class_t src_cls, H5T_class_t dst_cls, H5T_conv_t func) HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query"); } - if ((func) (src_id, dst_id, &cdata, 0, NULL, NULL) >= 0) { + + HDmemset (&cdata, 0, sizeof cdata); + if ((func) (src_id, dst_id, cdata, H5T_CONV_INIT, NULL, NULL) >= 0) { + /* + * Free resources used by the previous conversion function. We + * don't really care if this fails since at worst we'll just leak + * some memory. Then initialize the path with new info. + */ + if (path->soft) { + (path->soft)(src_id, dst_id, path->cdata, H5T_CONV_FREE, + NULL, NULL); + H5ECLEAR; + } path->soft = func; H5MM_xfree (path->cdata); path->cdata = cdata; + cdata = NULL; + + } else { + /* + * Notify soft function that it should recalculate its private + * data at the next opportunity. This is necessary because some + * functions cache a list of conversion functions in their + * private data area (see compound data type converters). + */ + path->cdata->recalc = TRUE; } + H5A_dec_ref(src_id); H5A_dec_ref(dst_id); H5ECLEAR; @@ -2168,7 +2211,7 @@ H5Tregister_soft(H5T_class_t src_cls, H5T_class_t dst_cls, H5T_conv_t func) FUNC_LEAVE(SUCCEED); } - + /*------------------------------------------------------------------------- * Function: H5Tunregister * @@ -2222,15 +2265,22 @@ H5Tunregister(H5T_conv_t func) /* Reset soft function */ if (path->soft == func) { path->soft = NULL; - path->cdata = H5MM_xfree (path->cdata); + /* + * Free old cdata entry. The conversion function is responsible + * for freeing the `priv' member and all it points to, but we'll + * free the rest of cdata here. + */ + (func)(FAIL, FAIL, path->cdata, H5T_CONV_FREE, NULL, NULL); + H5ECLEAR; + for (j=H5T_nsoft_g-1; j>=0 && !path->soft; --j) { - void *cdata = NULL; if (path->src->type != H5T_soft_g[j].src || path->dst->type != H5T_soft_g[j].dst) { continue; } + /* * Conversion functions are app-level, so temporarily create * object id's for the data types. @@ -2242,15 +2292,22 @@ H5Tunregister(H5T_conv_t func) HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register conv types for query"); } - if ((H5T_soft_g[j].func)(src_id, dst_id, &cdata, 0, + + HDmemset (path->cdata, 0, sizeof(H5T_cdata_t)); + if ((H5T_soft_g[j].func)(src_id, dst_id, path->cdata, 0, NULL, NULL) >= 0) { path->soft = H5T_soft_g[j].func; - path->cdata = cdata; } H5A_dec_ref(src_id); H5A_dec_ref(dst_id); H5ECLEAR; } + } else { + /* + * If the soft function didn't change then make sure it + * recalculates its private data at the next opportunity. + */ + path->cdata->recalc = TRUE; } } @@ -2278,7 +2335,7 @@ H5Tunregister(H5T_conv_t func) *------------------------------------------------------------------------- */ H5T_conv_t -H5Tfind(hid_t src_id, hid_t dst_id, void **pcdata) +H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata) { H5T_conv_t ret_value = NULL; H5T_t *src = NULL, *dst = NULL; @@ -2946,10 +3003,11 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2) *------------------------------------------------------------------------- */ H5T_conv_t -H5T_find(const H5T_t *src, const H5T_t *dst, void **pcdata) +H5T_find(const H5T_t *src, const H5T_t *dst, H5T_cdata_t **pcdata) { - H5T_path_t *path = NULL; - H5T_conv_t ret_value = NULL; + H5T_path_t *path = NULL; + H5T_conv_t ret_value = NULL; + static H5T_cdata_t noop_cdata; FUNC_ENTER(H5T_find, NULL); @@ -2959,7 +3017,11 @@ H5T_find(const H5T_t *src, const H5T_t *dst, void **pcdata) assert (pcdata); /* No-op case */ - if (0 == H5T_cmp(src, dst)) HRETURN(H5T_conv_noop); + if (0 == H5T_cmp(src, dst)) { + *pcdata = &noop_cdata; + HRETURN(H5T_conv_noop); + } + /* Find it */ if (NULL == (path = H5T_path_find(src, dst, TRUE))) { @@ -3000,7 +3062,7 @@ H5T_find(const H5T_t *src, const H5T_t *dst, void **pcdata) * *------------------------------------------------------------------------- */ -H5T_path_t * +H5T_path_t * H5T_path_find(const H5T_t *src, const H5T_t *dst, hbool_t create) { intn lt = 0; /*left edge (inclusive) */ @@ -3052,10 +3114,10 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, hbool_t create) HDmemset(path, 0, sizeof(H5T_path_t)); path->src = H5T_copy(src); path->dst = H5T_copy(dst); + path->cdata = H5MM_xcalloc (1, sizeof(H5T_cdata_t)); /* Locate soft function */ for (i=H5T_nsoft_g-1; i>=0 && !path->soft; --i) { - void *cdata = NULL; if (src->type!=H5T_soft_g[i].src || dst->type!=H5T_soft_g[i].dst) { continue; @@ -3065,10 +3127,9 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, hbool_t create) HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conv types for query"); } - if ((H5T_soft_g[i].func) (src_id, dst_id, &cdata, 0, - NULL, NULL) >= 0) { + if ((H5T_soft_g[i].func) (src_id, dst_id, path->cdata, + H5T_CONV_INIT, NULL, NULL) >= 0) { path->soft = H5T_soft_g[i].func; - path->cdata = cdata; } H5A_dec_ref(src_id); H5A_dec_ref(dst_id); @@ -3077,7 +3138,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, hbool_t create) } FUNC_LEAVE(path); } - + /*------------------------------------------------------------------------- * Function: H5T_debug * diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 48d45ef..c30f8d7 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -14,6 +14,15 @@ #include <H5MMprivate.h> #include <H5Tpkg.h> +/* Conversion data for H5T_conv_struct() */ +typedef struct H5T_conv_struct_t { + intn *src2dst; /*mapping from src to dst memb ID */ + hid_t *src_memb_id; /*source member type ID's */ + hid_t *dst_memb_id; /*destination member type ID's */ + H5T_conv_t *memb_conv; /*array of membr conversion functions*/ + H5T_cdata_t **memb_cdata; /*array of member cdata pointers */ +} H5T_conv_struct_t; + /* Interface initialization */ static intn interface_initialize_g = FALSE; #define INTERFACE_INIT NULL @@ -36,7 +45,7 @@ static intn interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ herr_t -H5T_conv_noop(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts, +H5T_conv_noop(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *buf, void *background) { FUNC_ENTER(H5T_conv_noop, FAIL); @@ -63,7 +72,7 @@ H5T_conv_noop(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts, *------------------------------------------------------------------------- */ herr_t -H5T_conv_order(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts, +H5T_conv_order(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *_buf, void *background) { uint8 *buf = (uint8 *) _buf; @@ -134,6 +143,127 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts, } /*------------------------------------------------------------------------- + * Function: H5T_conv_struct_init + * + * Purpose: Initialize the `priv' field of `cdata' with conversion + * information that is relatively constant. If `priv' is + * already initialized then the member conversion functions + * are recalculated. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, January 26, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) +{ + H5T_conv_struct_t *priv = (H5T_conv_struct_t*)(cdata->priv); + intn i, j, *src2dst = NULL; + H5T_t *type = NULL; + hid_t tid; + + FUNC_ENTER (H5T_conv_struct_init, FAIL); + + if (!priv) { + /* + * Notice: the thing marked with `!' below really is `dst' and not + * `src' because we're only interested in the members of the + * source type that are also in the destination type. + */ + cdata->priv = priv = H5MM_xcalloc (1, sizeof(H5T_conv_struct_t)); + priv->src2dst = H5MM_xmalloc (src->u.compnd.nmembs * sizeof(intn)); + priv->src_memb_id = H5MM_xmalloc (/*!*/dst->u.compnd.nmembs * + sizeof(hid_t)); + priv->dst_memb_id = H5MM_xmalloc (dst->u.compnd.nmembs * + sizeof(hid_t)); + + /* + * Insure that members are sorted. + */ + H5T_sort_by_offset (src); + H5T_sort_by_offset (dst); + + /* + * 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 data type so we can look up the + * member data type conversion functions later. + */ + for (i=0; i<src->u.compnd.nmembs; i++) { + priv->src2dst[i] = -1; + for (j=0; j<dst->u.compnd.nmembs; j++) { + if (!HDstrcmp (src->u.compnd.memb[i].name, + dst->u.compnd.memb[j].name)) { + priv->src2dst[i] = j; + break; + } + } + if (priv->src2dst[i]>=0) { + type = &(src->u.compnd.memb[i].type); + tid = H5A_register (H5_DATATYPE, type); + assert (tid>=0); + priv->src_memb_id[priv->src2dst[i]] = tid; + + type = &(dst->u.compnd.memb[priv->src2dst[i]].type); + tid = H5A_register (H5_DATATYPE, type); + assert (tid>=0); + priv->dst_memb_id[priv->src2dst[i]] = tid; + } + } + } + + /* + * (Re)build the cache of member conversion functions and pointers to + * their cdata entries. + */ + priv->memb_conv = H5MM_xfree (priv->memb_conv); + priv->memb_cdata = H5MM_xfree (priv->memb_cdata); + priv->memb_conv = H5MM_xmalloc (dst->u.compnd.nmembs * + sizeof(H5T_conv_t)); + priv->memb_cdata = H5MM_xcalloc (dst->u.compnd.nmembs, + sizeof(H5T_cdata_t*)); + src2dst = priv->src2dst; + + for (i=0; i<src->u.compnd.nmembs; i++) { + if (priv->src2dst[i]>=0) { + H5T_conv_t tconv_func = H5Tfind (priv->src_memb_id[src2dst[i]], + priv->dst_memb_id[src2dst[i]], + priv->memb_cdata+src2dst[i]); + if (!tconv_func) { + H5MM_xfree (priv->src2dst); + H5MM_xfree (priv->src_memb_id); + H5MM_xfree (priv->dst_memb_id); + H5MM_xfree (priv->memb_conv); + cdata->priv = priv = H5MM_xfree (priv); + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unable to convert member data type"); + } + priv->memb_conv[src2dst[i]] = tconv_func; + } + } + +#ifndef LATER + /* + * Always use an initialized background buffer. Actually, we usually + * won't need it initialized but we'll almost always need a buffer to + * move the members around. + */ + cdata->need_bkg = H5T_BKG_YES; +#endif + + cdata->recalc = FALSE; + FUNC_LEAVE (SUCCEED); +} + +/*------------------------------------------------------------------------- * Function: H5T_conv_struct * * Purpose: Converts between compound data types. This is a soft @@ -163,38 +293,37 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts, *------------------------------------------------------------------------- */ herr_t -H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, size_t nelmts, +H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *_buf, void *_bkg) { - H5T_conv_struct_t **pcdata = (H5T_conv_struct_t **)_pcdata; uint8 *buf = (uint8 *)_buf; /*cast for pointer arithmetic */ uint8 *bkg = (uint8 *)_bkg; /*background pointer arithmetic */ H5T_t *src = NULL; /*source data type */ H5T_t *dst = NULL; /*destination data type */ - H5T_t *type = NULL; /*temporary type pointer */ - hid_t tid; /*temporary type ID */ intn *src2dst = NULL; /*maps src member to dst member */ H5T_member_t *src_memb = NULL; /*source struct member descript.*/ H5T_member_t *dst_memb = NULL; /*destination struct memb desc. */ - H5T_conv_t tconv_func = NULL; /*member data type conv. func. */ size_t offset; /*byte offset wrt struct */ size_t src_delta, dst_delta; /*source & destination stride */ - intn elmtno, i, j; /*counters */ - void *memb_cdata = NULL; /*member conversion data */ + intn elmtno, i; /*counters */ herr_t ret_value = FAIL; + H5T_conv_struct_t *priv = (H5T_conv_struct_t *)(cdata->priv); FUNC_ENTER (H5T_conv_struct, FAIL); - /* Check args */ - if (H5_DATATYPE != H5A_group(src_id) || - NULL == (src = H5A_object(src_id)) || - H5_DATATYPE != H5A_group(dst_id) || - NULL == (dst = H5A_object(dst_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - } - - /* Capability query? */ - if (!buf) { + if (!buf && H5T_CONV_INIT==nelmts) { + /* + * First, determine if this conversion function applies to the + * conversion path SRC_ID-->DST_ID. If not, return failure; + * otherwise initialize the `priv' field of `cdata' with information + * that remains (almost) constant for this conversion path. + */ + if (H5_DATATYPE != H5A_group(src_id) || + NULL == (src = H5A_object(src_id)) || + H5_DATATYPE != H5A_group(dst_id) || + NULL == (dst = H5A_object(dst_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } assert (H5T_COMPOUND==src->type); assert (H5T_COMPOUND==dst->type); @@ -203,84 +332,66 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, size_t nelmts, * Struct members must be scalar for now. */ for (i=0; i<src->u.compnd.nmembs; i++) { - assert (0==src->u.compnd.memb[i].ndims); + if (src->u.compnd.memb[i].ndims>0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "array members are not supported yet"); + } } for (i=0; i<dst->u.compnd.nmembs; i++) { - assert (0==dst->u.compnd.memb[i].ndims); + if (dst->u.compnd.memb[i].ndims>0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "array members are not supported yet"); + } } #endif - /* - * Okay, we've determined that this conversion function applies to - * the data types supplied as arguments. Now we build information - * which is expensive to calculate but is constant for all - * conversions from SRC_ID to DST_ID. Notice: the thing marked with - * `!' really is `dst' and not `src' because we're only interested in - * the members of the source type that are also in the destination - * type. - */ - assert (pcdata); - *pcdata = H5MM_xcalloc (1, sizeof(H5T_conv_struct_t)); - src2dst = H5MM_xmalloc (src->u.compnd.nmembs * sizeof(intn)); - (*pcdata)->src2dst = src2dst; - (*pcdata)->src_memb_id = H5MM_xmalloc (/*!*/dst->u.compnd.nmembs * - sizeof(hid_t)); - (*pcdata)->dst_memb_id = H5MM_xmalloc (dst->u.compnd.nmembs * - sizeof(hid_t)); - - /* - * Insure that members are sorted. - */ - H5T_sort_by_offset (src); - H5T_sort_by_offset (dst); - - /* - * 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 data type so we can look up the - * member data type conversion functions later. - */ - for (i=0; i<src->u.compnd.nmembs; i++) { - src2dst[i] = -1; - for (j=0; j<dst->u.compnd.nmembs; j++) { - if (!HDstrcmp (src->u.compnd.memb[i].name, - dst->u.compnd.memb[j].name)) { - src2dst[i] = j; - break; - } - } - if (src2dst[i]>=0) { - type = &(src->u.compnd.memb[i].type); - tid = H5A_register (H5_DATATYPE, type); - assert (tid>=0); - (*pcdata)->src_memb_id[i] = tid; - - type = &(dst->u.compnd.memb[src2dst[i]].type); - tid = H5A_register (H5_DATATYPE, type); - assert (tid>=0); - (*pcdata)->dst_memb_id[i] = tid; - } + if (H5T_conv_struct_init (src, dst, cdata)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to initialize conversion data"); } - + HRETURN (SUCCEED); + } else if (!buf && H5T_CONV_FREE==nelmts) { + /* + * Free the private conversion data. + */ + H5MM_xfree (priv->src2dst); + H5MM_xfree (priv->src_memb_id); + H5MM_xfree (priv->dst_memb_id); + H5MM_xfree (priv->memb_conv); + cdata->priv = priv = H5MM_xfree (priv); HRETURN (SUCCEED); + + } else if (!buf) { + /* Some other command we don't know about yet.*/ + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unknown conversion command"); + } + + + /* Check args */ + if (H5_DATATYPE != H5A_group(src_id) || + NULL == (src = H5A_object(src_id)) || + H5_DATATYPE != H5A_group(dst_id) || + NULL == (dst = H5A_object(dst_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); } + assert (priv); + assert (bkg && cdata->need_bkg>=H5T_BKG_TEMP); - /* - * Here comes the real conversion... - */ - assert (pcdata && *pcdata); - assert ((*pcdata)->src2dst); - assert ((*pcdata)->src_memb_id); - assert ((*pcdata)->dst_memb_id); + if (cdata->recalc && + H5T_conv_struct_init (src, dst, cdata)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to initialize conversion data"); + } + /* * Insure that members are sorted. */ H5T_sort_by_offset (src); H5T_sort_by_offset (dst); - src2dst = (*pcdata)->src2dst; + src2dst = priv->src2dst; /* * Direction of conversion. @@ -309,15 +420,10 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, size_t nelmts, dst_memb = dst->u.compnd.memb + src2dst[i]; if (dst_memb->type.size <= src_memb->type.size) { - tconv_func = H5T_find (&(dst_memb->type), &(src_memb->type), - &memb_cdata); - if (!tconv_func) { - HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, - "unable to convert member data type"); - } - - (tconv_func)((*pcdata)->src_memb_id[i], - (*pcdata)->dst_memb_id[i], &memb_cdata, 1, + H5T_conv_t tconv_func = priv->memb_conv[src2dst[i]]; + H5T_cdata_t *memb_cdata = priv->memb_cdata[src2dst[i]]; + (tconv_func)(priv->src_memb_id[src2dst[i]], + priv->dst_memb_id[src2dst[i]], memb_cdata, 1, buf + src_memb->offset, bkg + dst_memb->offset); HDmemmove (buf + offset, buf + src_memb->offset, @@ -343,15 +449,10 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, size_t nelmts, offset -= dst_memb->type.size; if (dst_memb->type.size > src_memb->type.size) { - tconv_func = H5T_find (&(src_memb->type), &(dst_memb->type), - &memb_cdata); - if (!tconv_func) { - HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, - "unable to convert member data type"); - } - - (tconv_func)((*pcdata)->src_memb_id[i], - (*pcdata)->dst_memb_id[i], &memb_cdata, 1, + H5T_conv_t tconv_func = priv->memb_conv[src2dst[i]]; + H5T_cdata_t *memb_cdata = priv->memb_cdata[src2dst[i]]; + (tconv_func)(priv->src_memb_id[src2dst[i]], + priv->dst_memb_id[src2dst[i]], memb_cdata, 1, buf + offset, bkg + dst_memb->offset); } HDmemmove (bkg+dst_memb->offset, buf+offset, dst_memb->type.size); @@ -371,7 +472,6 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, size_t nelmts, HDmemcpy (_buf, _bkg, nelmts*dst->size); ret_value = SUCCEED; - done: FUNC_LEAVE (ret_value); } diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 7fa5811..7c86500 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -78,7 +78,7 @@ typedef struct H5T_path_t { H5T_t *dst; /*destination data type ID */ H5T_conv_t hard; /*hard conversion function or null */ H5T_conv_t soft; /*soft conversion function or null */ - void *cdata; /*extra conversion data */ + H5T_cdata_t *cdata; /*extra conversion data */ } H5T_path_t; /* The master list of soft conversion functions */ @@ -88,23 +88,16 @@ typedef struct H5T_soft_t { H5T_conv_t func; /*the conversion function */ } H5T_soft_t; -/* Conversion data for H5T_conv_struct() */ -typedef struct H5T_conv_struct_t { - intn *src2dst; /*mapping from src to dst memb ID */ - hid_t *src_memb_id; /*source member type ID's */ - hid_t *dst_memb_id; /*destination member type ID's */ -} H5T_conv_struct_t; - /* Function prototypes for H5T package scope */ H5T_path_t *H5T_path_find (const H5T_t *src, const H5T_t *dst, hbool_t create); /* Conversion functions */ -herr_t H5T_conv_noop (hid_t src_id, hid_t dst_id, void **pcdata, +herr_t H5T_conv_noop (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *buf, void *bkg); -herr_t H5T_conv_order (hid_t src_id, hid_t dst_id, void **pcdata, +herr_t H5T_conv_order (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *_buf, void *bkg); -herr_t H5T_conv_struct (hid_t src_id, hid_t dst_id, void **pcdata, +herr_t H5T_conv_struct (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *_buf, void *bkg); diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 8a1b940..d67c38d 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -40,5 +40,5 @@ herr_t H5T_insert (H5T_t *parent, const char *name, off_t offset, herr_t H5T_sort_by_offset (H5T_t *dt); herr_t H5T_pack (H5T_t *dt); herr_t H5T_debug (H5T_t *dt, FILE * stream); -H5T_conv_t H5T_find (const H5T_t *src, const H5T_t *dst, void **pcdata); +H5T_conv_t H5T_find (const H5T_t *src, const H5T_t *dst, H5T_cdata_t **pcdata); #endif diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 6c89e14..aebf33c 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -23,6 +23,9 @@ #define HOFFSET(S,M) ((const char*)&S.M-(const char*)&S) #define HPOFFSET(P,M) ((const char*)&(P->M)-(const char*)P) +#define H5T_CONV_INIT 0 +#define H5T_CONV_FREE 1 + /* These are the various classes of data types */ typedef enum H5T_class_t { H5T_NO_CLASS = -1, /*error */ @@ -92,8 +95,22 @@ typedef enum H5T_pad_t { H5T_NPAD = 3 /*THIS MUST BE LAST */ } H5T_pad_t; +/* How is the `bkg' buffer used by the conversion function? */ +typedef enum H5T_bkg_t { + H5T_BKG_NONE = 0, /*background buffer is not needed, send NULL */ + H5T_BKG_TEMP = 1, /*bkg buffer used as temp storage only */ + H5T_BKG_YES = 2, /*init bkg buf with data before conversion */ +} H5T_bkg_t; + +/* Type conversion client data */ +typedef struct H5T_cdata_t { + H5T_bkg_t need_bkg;/*is the background buffer needed? */ + hbool_t recalc; /*recalculate private data */ + void *priv; /*private data */ +} H5T_cdata_t; + /* All data type conversion functions are... */ -typedef herr_t (*H5T_conv_t) (hid_t src_id, hid_t dst_id, void **pcdata, +typedef herr_t (*H5T_conv_t) (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, void *buf, void *bkg); /* The predefined types */ @@ -209,7 +226,7 @@ herr_t H5Tset_strpad (hid_t type_id, H5T_str_t strpad); herr_t H5Tregister_hard (hid_t src_id, hid_t dst_id, H5T_conv_t func); herr_t H5Tregister_soft (H5T_class_t src, H5T_class_t dst, H5T_conv_t func); herr_t H5Tunregister (H5T_conv_t func); -H5T_conv_t H5Tfind (hid_t src_id, hid_t dst_id, void **pcdata); +H5T_conv_t H5Tfind (hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata); #ifdef __cplusplus } diff --git a/test/cmpd_dset.c b/test/cmpd_dset.c index 3676890..b0586f6 100644 --- a/test/cmpd_dset.c +++ b/test/cmpd_dset.c @@ -50,8 +50,8 @@ typedef struct s5_t { } s5_t; -#define NX 10 -#define NY 200 +#define NX 100 +#define NY 2000 static hid_t @@ -278,6 +278,7 @@ STEP 5: Read members into a superset which is partially initialized.\n"); /* Read the data */ status = H5Dread (dataset, s5_tid, H5P_ALL, H5P_ALL, H5C_DEFAULT, s5); + assert (status>=0); /* Check that the data was read properly */ for (i=0; i<NX*NY; i++) { @@ -295,6 +296,46 @@ STEP 5: Read members into a superset which is partially initialized.\n"); assert (s5[i].mid2 == 1002+4*i); assert (s5[i].post == 1003+4*i); } + + /* + *###################################################################### + * STEP 6: Update fields `b' and `d' on the file leaving the other + * fields unchanged. This tests member alignment and background + * buffers. + */ + printf ("\ +STEP 6: Update fields `b' and `d' on the file, leaving the other fields\n\ + unchanged.\n"); + fflush (stdout); + + /* Initialize `s4' with new values */ + for (i=0; i<NX*NY; i++) { + s4[i].b = 2000+2*i; + s4[i].d = 2001+2*i; + } + + /* Write the data to file */ + status = H5Dwrite (dataset, s4_tid, H5P_ALL, H5P_ALL, H5C_DEFAULT, s4); + assert (status>=0); + + /* Read the data back */ + status = H5Dread (dataset, s2_tid, H5P_ALL, H5P_ALL, H5C_DEFAULT, s2); + assert (status>=0); + + /* Compare */ + for (i=0; i<NX*NY; i++) { + assert (s2[i].a == s1[i].a); + assert (s2[i].b == s4[i].b); + assert (s2[i].c == s1[i].c); + assert (s2[i].d == s4[i].d); + assert (s2[i].e == s1[i].e); + } + + + + + + /* |