summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-01-23 19:53:37 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-01-23 19:53:37 (GMT)
commit6ee36e2b3afbddc4e9c1a20040132492d5b407ba (patch)
treebcaf153ccb985b480e989d7f84d8343ab2c2f8a6 /src/H5Tconv.c
parentdd36e4a3419ae1f1102c7aa3bcdfa4aec8b7ce88 (diff)
downloadhdf5-6ee36e2b3afbddc4e9c1a20040132492d5b407ba.zip
hdf5-6ee36e2b3afbddc4e9c1a20040132492d5b407ba.tar.gz
hdf5-6ee36e2b3afbddc4e9c1a20040132492d5b407ba.tar.bz2
[svn-r168] Changes since 19980122
---------------------- ./MANIFEST Added new files. ./src/H5D.c Added support for partial datatype I/O which is needed when merging struct members between file and disk. This isn't the efficient version because the merge requires an extra gather (step 1b in my pipeline diagram) that isn't turned off when it isn't needed. ./src/H5T.c ./src/H5Tpkg.h ./src/H5Tprivate.h ./src/H5Tpublic.h Conversion functions take an extra argument which is a pointer to a blob of private data that can be used by the conversion function to save anything that's expensive to compute and is constant for a particular conversion path. ./src/H5Tconv.c Compound data type conversion is beginning to work! We can handle conversions between compound types that have members which are not arrays. It also supports partial conversion so we can omit certain members of the source and not clobber extra members in the destination. ./test/Makefile.in ./test/cmpd_dset.c [NEW] Added a test case that demonstrates how to use compound data types in a dataset. The output doesn't match the output of the other test cases yet, the the entire example is more readable and written entirely with the API.
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c224
1 files changed, 177 insertions, 47 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index ff612ba..48d45ef 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -36,8 +36,8 @@ static intn interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_noop(hid_t src_id, hid_t dst_id, size_t nelmts,
- void *buf, const void *background)
+H5T_conv_noop(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts,
+ void *buf, void *background)
{
FUNC_ENTER(H5T_conv_noop, FAIL);
FUNC_LEAVE(SUCCEED);
@@ -63,8 +63,8 @@ H5T_conv_noop(hid_t src_id, hid_t dst_id, size_t nelmts,
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_order(hid_t src_id, hid_t dst_id, size_t nelmts,
- void *_buf, const void *background)
+H5T_conv_order(hid_t src_id, hid_t dst_id, void **pcdata, size_t nelmts,
+ void *_buf, void *background)
{
uint8 *buf = (uint8 *) _buf;
uint8 tmp;
@@ -81,10 +81,6 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, size_t nelmts,
NULL == (dst = H5A_object(dst_id))) {
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
}
- if (background) {
- HRETURN_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL,
- "background values not supported in this conv path");
- }
if (!buf) {
/* Capability query */
@@ -123,6 +119,7 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, size_t nelmts,
}
HRETURN(SUCCEED);
}
+
/* The conversion */
md = src->size / 2;
for (i = 0; i < nelmts; i++, buf += src->size) {
@@ -166,15 +163,26 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, size_t nelmts,
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_struct(hid_t src_id, hid_t dst_id, size_t nelmts,
- void *_buf, const void *background)
+H5T_conv_struct(hid_t src_id, hid_t dst_id, void **_pcdata, 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 */
- intn *dst2src_map = NULL; /*maps dst member to src member */
- intn i;
-
+ 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 */
+ herr_t ret_value = FAIL;
+
FUNC_ENTER (H5T_conv_struct, FAIL);
/* Check args */
@@ -184,64 +192,186 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, size_t nelmts,
NULL == (dst = H5A_object(dst_id))) {
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
}
- if (background) {
- HRETURN_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL,
- "background values not supported in this conv path");
- }
/* Capability query? */
if (!buf) {
assert (H5T_COMPOUND==src->type);
assert (H5T_COMPOUND==dst->type);
- HRETURN (SUCCEED);
- }
- /*
- * Build a mapping from destination member number to source member number
- */
- H5T_sort_by_offset (src);
- H5T_sort_by_offset (dst);
- dst2src_map = H5MM_xmalloc (dst->u.compnd.nmembs * sizeof(intn));
- for (i=0; i<src->u.compnd.nmembs; i++) {
- }
+#ifndef LATER
+ /*
+ * Struct members must be scalar for now.
+ */
+ for (i=0; i<src->u.compnd.nmembs; i++) {
+ assert (0==src->u.compnd.memb[i].ndims);
+ }
+ for (i=0; i<dst->u.compnd.nmembs; i++) {
+ assert (0==dst->u.compnd.memb[i].ndims);
+ }
+#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);
- /*
- * For each source member which will be present in the destination,
- * convert the member to the destination type unless it is larger than
- * the source type. Then move the member to the left-most unoccupied
- * position in the buffer. This makes the data point as small as
- * possible with all the free space on the right side.
- */
- for (i=0; i<src->u.compnd.nmembs; i++) {
- }
+ /*
+ * 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;
+ }
+ }
+
+
+ HRETURN (SUCCEED);
+ }
/*
- * For each source member which will be present in the destination,
- * convert the member to the destination type if it is larger than the
- * source type (that is, has not been converted yet). Then copy the
- * member to the destination offset in the background buffer.
+ * Here comes the real conversion...
*/
- for (i=src->u.compnd.nmembs-1; i>=0; --i) {
- }
+ assert (pcdata && *pcdata);
+ assert ((*pcdata)->src2dst);
+ assert ((*pcdata)->src_memb_id);
+ assert ((*pcdata)->dst_memb_id);
-
/*
- * Copy the background buffer back into the in-place conversion buffer.
+ * Insure that members are sorted.
*/
- HDmemcpy (buf, background, dst->size);
+ H5T_sort_by_offset (src);
+ H5T_sort_by_offset (dst);
+ src2dst = (*pcdata)->src2dst;
+ /*
+ * Direction of conversion.
+ */
+ if (dst->size <= src->size) {
+ src_delta = src->size;
+ dst_delta = dst->size;
+ } else {
+ src_delta = -(src->size);
+ dst_delta = -(dst->size);
+ buf += (nelmts-1) * src->size;
+ bkg += (nelmts-1) * dst->size;
+ }
+ for (elmtno=0; elmtno<nelmts; elmtno++) {
+ /*
+ * For each source member which will be present in the destination,
+ * convert the member to the destination type unless it is larger than
+ * the source type. Then move the member to the left-most unoccupied
+ * position in the buffer. This makes the data point as small as
+ * possible with all the free space on the right side.
+ */
+ for (i=0, offset=0; i<src->u.compnd.nmembs; i++) {
+ if (src2dst[i]<0) continue;
+ src_memb = src->u.compnd.memb + i;
+ 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,
+ buf + src_memb->offset, bkg + dst_memb->offset);
+ HDmemmove (buf + offset, buf + src_memb->offset,
+ dst_memb->type.size);
+ offset += dst_memb->type.size;
+ } else {
+ HDmemmove (buf + offset, buf + src_memb->offset,
+ src_memb->type.size);
+ offset += src_memb->type.size;
+ }
+ }
+ /*
+ * For each source member which will be present in the destination,
+ * convert the member to the destination type if it is larger than the
+ * source type (that is, has not been converted yet). Then copy the
+ * member to the destination offset in the background buffer.
+ */
+ for (i=src->u.compnd.nmembs-1; i>=0; --i) {
+ if (src2dst[i]<0) continue;
+ src_memb = src->u.compnd.memb + i;
+ dst_memb = dst->u.compnd.memb + src2dst[i];
+ 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,
+ buf + offset, bkg + dst_memb->offset);
+ }
+ HDmemmove (bkg+dst_memb->offset, buf+offset, dst_memb->type.size);
+ }
+ assert (0==offset);
+ /*
+ * Update buf and background.
+ */
+ buf += src_delta;
+ bkg += dst_delta;
+ }
- HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "not implemented yet");
- FUNC_LEAVE (SUCCEED);
+ /*
+ * Copy the background buffer back into the in-place conversion buffer.
+ */
+ HDmemcpy (_buf, _bkg, nelmts*dst->size);
+ ret_value = SUCCEED;
+
+ done:
+ FUNC_LEAVE (ret_value);
}