diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2008-09-22 23:41:31 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2008-09-22 23:41:31 (GMT) |
commit | 5bbc0eedffa32de995e993a19d345f491fc1695c (patch) | |
tree | d733f4321b20a1842da72f30e7b2b2ab18fcc1f5 /src/H5Tconv.c | |
parent | fe6cf16d94aeface4e429660142b243f471f8fbb (diff) | |
download | hdf5-5bbc0eedffa32de995e993a19d345f491fc1695c.zip hdf5-5bbc0eedffa32de995e993a19d345f491fc1695c.tar.gz hdf5-5bbc0eedffa32de995e993a19d345f491fc1695c.tar.bz2 |
[svn-r15682] Purpose: fix bug 1298
Description: The optimized "subset" compound conversion function would
improperly copy the "blank" space at the end of compound types. Modified
H5T_conv_struct_init to detect when the subset type has extra space at the end,
and calculate the size of the data that should be copied into the conversion
buffer for each element. Changes to the functions that implement these
conversions.
Tested: kagiso, linew, smirom (h5committest)
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r-- | src/H5Tconv.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 276d05a..b02e72a 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -883,7 +883,7 @@ typedef struct H5T_conv_struct_t { hid_t *src_memb_id; /*source member type ID's */ hid_t *dst_memb_id; /*destination member type ID's */ H5T_path_t **memb_path; /*conversion path for each member */ - H5T_subset_t smembs_subset; /*are source and dest members a subset of each other? */ + H5T_subset_info_t subset_info; /*info related to compound subsets */ } H5T_conv_struct_t; /* Conversion data for H5T_conv_enum() */ @@ -1827,7 +1827,8 @@ H5T_conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id) /* The flag of special optimization to indicate if source members and destination * members are a subset of each other. Initialize it to FALSE */ - priv->smembs_subset = H5T_SUBSET_FALSE; + priv->subset_info.subset = H5T_SUBSET_FALSE; + priv->subset_info.copy_size = 0; /* * Insure that members are sorted. @@ -1899,23 +1900,41 @@ H5T_conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id) cdata->need_bkg = H5T_BKG_YES; if(src_nmembs < dst_nmembs) { - priv->smembs_subset = H5T_SUBSET_SRC; + priv->subset_info.subset = H5T_SUBSET_SRC; for(i = 0; i < src_nmembs; i++) { /* If any of source members doesn't have counterpart in the same * order or there's conversion between members, don't do the * optimization. */ - if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) - priv->smembs_subset = H5T_SUBSET_FALSE; + if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) { + priv->subset_info.subset = H5T_SUBSET_FALSE; + break; + } /* end if */ } /* end for */ + /* Compute the size of the data to be copied for each element. It + * may be smaller than either src or dst if there is extra space at + * the end of src. + */ + if(priv->subset_info.subset == H5T_SUBSET_SRC) + priv->subset_info.copy_size = src->shared->u.compnd.memb[src_nmembs-1].offset + + src->shared->u.compnd.memb[src_nmembs-1].size; } else if(dst_nmembs < src_nmembs) { - priv->smembs_subset = H5T_SUBSET_DST; + priv->subset_info.subset = H5T_SUBSET_DST; for(i = 0; i < dst_nmembs; i++) { /* If any of source members doesn't have counterpart in the same order or * there's conversion between members, don't do the optimization. */ - if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) - priv->smembs_subset = H5T_SUBSET_FALSE; + if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) { + priv->subset_info.subset = H5T_SUBSET_FALSE; + break; + } } /* end for */ + /* Compute the size of the data to be copied for each element. It + * may be smaller than either src or dst if there is extra space at + * the end of dst. + */ + if(priv->subset_info.subset == H5T_SUBSET_DST) + priv->subset_info.copy_size = dst->shared->u.compnd.memb[dst_nmembs-1].offset + + dst->shared->u.compnd.memb[dst_nmembs-1].size; } else /* If the numbers of source and dest members are equal and no conversion is needed, * the case should have been handled as noop earlier in H5Dio.c. */ ; @@ -1945,14 +1964,15 @@ done: * TYPE5 E; * }; * - * Return: One of the value from H5T_subset_t. + * Return: A pointer to the subset info struct in p. Points directly + * into the structure. * * Programmer: Raymond Lu * 8 June 2007 * *------------------------------------------------------------------------- */ -H5T_subset_t +H5T_subset_info_t * H5T_conv_struct_subset(const H5T_cdata_t *cdata) { H5T_conv_struct_t *priv; @@ -1964,7 +1984,7 @@ H5T_conv_struct_subset(const H5T_cdata_t *cdata) priv = (H5T_conv_struct_t *)(cdata->priv); - FUNC_LEAVE_NOAPI(priv->smembs_subset) + FUNC_LEAVE_NOAPI((H5T_subset_info_t *) &priv->subset_info) } /* end H5T_conv_struct_subset() */ @@ -2388,22 +2408,12 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, buf_stride = src->shared->size; } - if(priv->smembs_subset == H5T_SUBSET_SRC || priv->smembs_subset == H5T_SUBSET_DST) { + if(priv->subset_info.subset == H5T_SUBSET_SRC || priv->subset_info.subset == H5T_SUBSET_DST) { /* If the optimization flag is set to indicate source members are a subset and * in the top of the destination, simply copy the source members to background buffer. */ xbuf = buf; xbkg = bkg; - if(dst->shared->size <= src->shared->size) - /* This is to deal with a very special situation when the fields and their - * offset for both source and destination are identical but the datatype - * sizes of source and destination are different. The library still - * considers these two types different and does conversion. It happens - * in table API test (hdf5/hl/test/test_table.c) when a table field is - * deleted. - */ - copy_size = dst->shared->size; - else - copy_size = src->shared->size; + copy_size = priv->subset_info.copy_size; for (elmtno=0; elmtno<nelmts; elmtno++) { HDmemmove(xbkg, xbuf, copy_size); |