summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index fe4e6c3..5a84ad1 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -14,6 +14,7 @@
#include <H5Eprivate.h>
#include <H5MMprivate.h>
#include <H5Tpkg.h>
+#include <H5TBprivate.h>
/* Conversion data for H5T_conv_struct() */
typedef struct H5T_conv_struct_t {
@@ -1383,6 +1384,213 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
/*-------------------------------------------------------------------------
+ * Function: H5T_conv_vlen
+ *
+ * Purpose: Converts between VL data types in memory and on disk.
+ * This is a soft conversion function. The algorithm is basically:
+ *
+ * For every VL struct in the main buffer:
+ * Allocate space for temporary dst VL data (reuse buffer if possible)
+ * Copy VL data from src buffer into dst buffer
+ * Convert VL data into dst representation
+ * Allocate buffer in dst heap
+ * Write dst VL data into dst heap
+ * Store (heap ID or pointer) and length in main dst buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, May 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
+ void *_buf, void UNUSED *_bkg)
+{
+ H5T_path_t *tpath; /* Type conversion path */
+ hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */
+ H5T_t *src = NULL; /*source data type */
+ H5T_t *dst = NULL; /*destination data type */
+ size_t olap; /*num overlapping elements */
+ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/
+ uint8_t **dptr; /* Pointer to correct destination pointer */
+ size_t src_delta, dst_delta; /*source & destination stride */
+ hsize_t seq_len; /* The number of elements in the current sequence */
+ size_t src_base_size, dst_base_size; /*source & destination base size */
+ size_t src_size, dst_size; /*source & destination total size in bytes */
+ hid_t conv_buf_id; /* ID for comversion buffer */
+ void *conv_buf_ptr; /* Temporary conversion buffer */
+ hsize_t conv_buf_size; /* Size of conversion buffer in bytes */
+ uint8_t dbuf[64],*dbuf_ptr=dbuf; /*temp destination buffer */
+ intn direction; /*direction of traversal */
+ uintn elmtno;
+
+ FUNC_ENTER (H5T_conv_struct, FAIL);
+
+ switch (cdata->command) {
+ case H5T_CONV_INIT:
+ /*
+ * 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 (H5I_DATATYPE != H5I_get_type(src_id) || NULL == (src = H5I_object(src_id)) ||
+ H5I_DATATYPE != H5I_get_type(dst_id) || NULL == (dst = H5I_object(dst_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ }
+ assert (H5T_VLEN==src->type);
+ assert (H5T_VLEN==dst->type);
+
+#ifdef LATER
+/* QAK - Set up conversion function? */
+ if (H5T_conv_vlen_init (src, dst, cdata)<0) {
+ HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
+ "unable to initialize conversion data");
+ }
+#endif /* LATER */
+ break;
+
+ case H5T_CONV_FREE:
+/* QAK - Nothing to do currently */
+ break;
+
+ case H5T_CONV_CONV:
+ /*
+ * Conversion.
+ */
+ if (H5I_DATATYPE != H5I_get_type(src_id) || NULL == (src = H5I_object(src_id)) ||
+ H5I_DATATYPE != H5I_get_type(dst_id) || NULL == (dst = H5I_object(dst_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ }
+
+ /*
+ * Do we process the values from beginning to end or vice versa? Also,
+ * how many of the elements have the source and destination areas
+ * overlapping?
+ */
+ if (src->size==dst->size) {
+ olap = nelmts;
+ sp = dp = (uint8_t*)_buf;
+ direction = 1;
+ } else if (src->size>=dst->size) {
+ olap = ((dst->size)/(src->size-dst->size))+1; /* potentially this uses the destination buffer 1 extra time, but its faster that floating-point calcs */
+ sp = dp = (uint8_t*)_buf;
+ direction = 1;
+ } else {
+ olap = nelmts-(((src->size)/(dst->size-src->size))+1); /* potentially this uses the destination buffer 1 extra time, but its faster that floating-point calcs */
+ sp = (uint8_t*)_buf + (nelmts-1) * src->size;
+ dp = (uint8_t*)_buf + (nelmts-1) * dst->size;
+ direction = -1;
+ }
+
+ /*
+ * Direction & size of buffer traversal.
+ */
+ src_delta = direction * src->size;
+ dst_delta = direction * dst->size;
+
+ /*
+ * If the source and destination buffers overlap then use a
+ * temporary buffer for the destination.
+ */
+ if (direction>0) {
+ dptr = &dbuf_ptr;
+ } else {
+ dptr = &dp;
+ }
+
+ /* Get the size of the base types in src & dst */
+ src_base_size=H5T_get_size(src->parent);
+ dst_base_size=H5T_get_size(dst->parent);
+
+ /* Get initial conversion buffer */
+ conv_buf_size=MAX(src_base_size,dst_base_size);
+ if((conv_buf_id=H5TB_get_buf(conv_buf_size,FALSE,&conv_buf_ptr))==FAIL)
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion");
+
+ /* Set up conversion path for base elements */
+ tpath = H5T_path_find(src->parent, dst->parent, NULL, NULL);
+ if (NULL==(tpath=H5T_path_find(src->parent, dst->parent, NULL, NULL))) {
+ HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types");
+ } else if (!H5T_IS_NOOP(tpath)) {
+ if ((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->parent, H5T_COPY_ALL)))<0 ||
+ (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->parent, H5T_COPY_ALL)))<0) {
+ HRETURN_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion");
+ }
+ }
+
+ for (elmtno=0; elmtno<nelmts; elmtno++) {
+ s = sp;
+ d = *dptr;
+
+ /* Get length of sequences in bytes */
+ seq_len=(*(src->u.vlen.getlen))(src->u.vlen.f,s);
+ src_size=seq_len*src_base_size;
+ dst_size=seq_len*dst_base_size;
+
+ /* Check if conversion buffer is large enough, resize if necessary */
+ if(conv_buf_size<MAX(src_size,dst_size)) {
+ conv_buf_size=MAX(src_size,dst_size);
+ if(H5TB_resize_buf(conv_buf_id,conv_buf_size,&conv_buf_ptr)<0)
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion");
+ } /* end if */
+
+ /* Read in VL sequence */
+ if((*(src->u.vlen.read))(src->u.vlen.f,s,conv_buf_ptr,src_size)<0)
+ HRETURN_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data");
+
+ /* Convert VL sequence */
+ if (H5T_convert(tpath, tsrc_id, tdst_id, seq_len, conv_buf_ptr, NULL)<0)
+ HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed");
+
+ /* Allocate new VL buffer */
+ if((*(dst->u.vlen.alloc))(dst->u.vlen.f,d,seq_len,dst_base_size)<0)
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for VL data");
+
+ /* Write sequence to destination location */
+ if((*(dst->u.vlen.write))(dst->u.vlen.f,d,conv_buf_ptr,dst_size)<0)
+ HRETURN_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data");
+
+ /*
+ * If we had used a temporary buffer for the destination then we
+ * should copy the value to the true destination buffer.
+ */
+ if (d==dbuf) HDmemcpy (dp, d, dst->size);
+ sp += src_delta;
+ dp += dst_delta;
+
+ /* switch destination pointer around when the olap gets to 0 */
+ if(--olap==0) {
+ if(dptr==&dbuf_ptr)
+ dptr=&dp;
+ else
+ dptr=&dbuf_ptr;
+ } /* end if */
+ }
+
+ /* Release the conversion buffer */
+ H5TB_release_buf(conv_buf_id);
+
+ /* Release the temporary datatype IDs used */
+ if (tsrc_id >= 0) H5I_dec_ref(tsrc_id);
+ if (tdst_id >= 0) H5I_dec_ref(tdst_id);
+
+ break;
+
+ default: /* Some other command we don't know about yet.*/
+ HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
+ "unknown conversion command");
+ } /* end switch */
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5T_conv_i_i
*
* Purpose: Convert one integer type to another. This is the catch-all