summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
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);
}