summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-01-26 20:56:18 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-01-26 20:56:18 (GMT)
commit5c6a3af39679b2bbbdaebf8f1c19edbeed7af248 (patch)
tree8c495a15af0ae785dfcb22420e197d583deef7ba
parent6cd8818b735d3c22f3a1f7cd30d52360139ed72c (diff)
downloadhdf5-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.c32
-rw-r--r--src/H5T.c107
-rw-r--r--src/H5Tconv.c300
-rw-r--r--src/H5Tpkg.h15
-rw-r--r--src/H5Tprivate.h2
-rw-r--r--src/H5Tpublic.h21
-rw-r--r--test/cmpd_dset.c45
7 files changed, 370 insertions, 152 deletions
diff --git a/src/H5D.c b/src/H5D.c
index dac599c..48723cd 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -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");
}
diff --git a/src/H5T.c b/src/H5T.c
index 87970bc..29d4df8 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -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);
+ }
+
+
+
+
+
+
/*