summaryrefslogtreecommitdiffstats
path: root/src/H5T.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5T.c')
-rw-r--r--src/H5T.c444
1 files changed, 318 insertions, 126 deletions
diff --git a/src/H5T.c b/src/H5T.c
index f1c2dbb..5d3c4a1 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -301,6 +301,9 @@
/* Local Typedefs */
/******************/
+/* Typedef for recursive const-correct datatype copying routines */
+typedef H5T_t *(*H5T_copy_func_t)(H5T_t *old_dt);
+
/********************/
/* Local Prototypes */
@@ -313,6 +316,11 @@ static herr_t H5T__set_size(H5T_t *dt, size_t size);
static herr_t H5T__close_cb(H5T_t *dt);
static H5T_path_t *H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv);
static hbool_t H5T__detect_vlen_ref(const H5T_t *dt);
+static H5T_t *H5T__initiate_copy(const H5T_t *old_dt);
+static H5T_t *H5T__copy_transient(H5T_t *old_dt);
+static H5T_t *H5T__copy_all(H5T_t *old_dt);
+static herr_t H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt,
+ H5T_shared_t *reopened_fo, hbool_t set_memory_type, H5T_copy_func_t copyfn);
/*****************************/
@@ -3304,132 +3312,152 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__create() */
-
+
/*-------------------------------------------------------------------------
- * Function: H5T_copy
+ * Function: H5T__initiate_copy
*
- * Purpose: Copies datatype OLD_DT. The resulting data type is not
- * locked and is a transient type.
+ * Purpose: Allocates datatype structures, copies core fields, and initializes
+ * VOL fields.
*
* Return: Success: Pointer to a new copy of the OLD_DT argument.
- *
* Failure: NULL
*
- * Programmer: Robb Matzke
- * Thursday, December 4, 1997
+ * Note: Common code for both H5T_copy and H5T_copy_reopen, as part of
+ * the const-correct datatype copying routines.
+ *
+ * Programmer: David Young
+ * January 18, 2020
*
*-------------------------------------------------------------------------
*/
-H5T_t *
-H5T_copy(H5T_t *old_dt, H5T_copy_t method)
+static H5T_t *
+H5T__initiate_copy(const H5T_t *old_dt)
{
- H5T_t *new_dt = NULL, *tmp = NULL;
- H5T_shared_t *reopened_fo = NULL;
- unsigned i;
- char *s;
- H5T_t *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
+ H5T_t *new_dt = NULL; /* Copy of datatype */
+ H5T_t *ret_value = NULL; /* Return value */
- /* check args */
- HDassert(old_dt);
+ FUNC_ENTER_STATIC
/* Allocate space */
if(NULL == (new_dt = H5FL_MALLOC(H5T_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_t memory allocation failed")
if(NULL == (new_dt->shared = H5FL_MALLOC(H5T_shared_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_shared_t memory allocation failed")
- /* Copy shared information (entry information is copied last) */
+ /* Copy shared information */
*(new_dt->shared) = *(old_dt->shared);
- /* No VOL object */
+ /* Reset VOL fields */
new_dt->vol_obj = NULL;
-
- /* No owned VOL object */
new_dt->shared->owned_vol_obj = NULL;
- /* Check what sort of copy we are making */
- switch (method) {
- case H5T_COPY_TRANSIENT:
- /*
- * Return an unlocked transient type.
- */
- new_dt->shared->state = H5T_STATE_TRANSIENT;
- break;
+ /* Set return value */
+ ret_value = new_dt;
- case H5T_COPY_ALL:
- /*
- * Return a transient type (locked or unlocked) or an unopened named
- * type. Immutable transient types are degraded to read-only.
- */
- if(H5T_STATE_OPEN==old_dt->shared->state)
- new_dt->shared->state = H5T_STATE_NAMED;
- else if(H5T_STATE_IMMUTABLE==old_dt->shared->state)
- new_dt->shared->state = H5T_STATE_RDONLY;
- break;
+done:
+ if(ret_value == NULL)
+ if(new_dt) {
+ if(new_dt->shared)
+ new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
+ new_dt = H5FL_FREE(H5T_t, new_dt);
+ } /* end if */
- case H5T_COPY_REOPEN:
- /*
- * Return a transient type (locked or unlocked) or an opened named
- * type. Immutable transient types are degraded to read-only.
- */
- if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
- /* Check if the object is already open */
- if(NULL == (reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) {
- /* Clear any errors from H5FO_opened() */
- H5E_clear_stack(NULL);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__initiate_copy() */
- /* Open named datatype again */
- if(H5O_open(&old_dt->oloc) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type")
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__copy_transient
+ *
+ * Purpose: Part of recursive framework for const-correct datatype copying.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_DT argument.
+ * Failure: NULL
+ *
+ * Programmer: David Young
+ * January 18, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5T_t *
+H5T__copy_transient(H5T_t *old_dt)
+{
+ H5T_t *ret_value = NULL; /* Return value */
- /* Insert opened named datatype into opened object list for the file */
- if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects")
+ FUNC_ENTER_STATIC
- /* Increment object count for the object in the top file */
- if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
+ /* Copy datatype, with correct method */
+ if(NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'transient' copy of datatype")
- new_dt->shared->fo_count = 1;
- } /* end if */
- else {
- /* The object is already open. Free the H5T_shared_t struct
- * we had been using and use the one that already exists.
- * Not terribly efficient. */
- new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
- new_dt->shared = reopened_fo;
-
- reopened_fo->fo_count++;
-
- /* Check if the object has been opened through the top file yet */
- if(H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) {
- /* Open the object through this top file */
- if(H5O_open(&old_dt->oloc) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header")
- } /* end if */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__copy_transient() */
- /* Increment object count for the object in the top file */
- if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
- } /* end else */
- new_dt->shared->state = H5T_STATE_OPEN;
- }
- else if(H5T_STATE_IMMUTABLE == old_dt->shared->state) {
- new_dt->shared->state = H5T_STATE_RDONLY;
- }
- break;
- default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type")
- } /* end switch */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__copy_all
+ *
+ * Purpose: Part of recursive framework for const-correct datatype copying.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_DT argument.
+ * Failure: NULL
+ *
+ * Programmer: David Young
+ * January 18, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5T_t *
+H5T__copy_all(H5T_t *old_dt)
+{
+ H5T_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Copy datatype, with correct method */
+ if(NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'all' copy of datatype")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__copy_transient() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__complete_copy
+ *
+ * Purpose: Completes copying datatype fields, as part of the recursive
+ * const-correct datatype copy routines.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Note: Common code for both H5T_copy and H5T_copy_reopen.
+ *
+ * Programmer: David Young
+ * January 18, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo,
+ hbool_t set_memory_type, H5T_copy_func_t copyfn)
+{
+ H5T_t *tmp = NULL; /* Temporary copy of compound field's datatype */
+ char *s; /* Temporary copy of compound field name / enum value name */
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
/* Update fields in the new struct, if we aren't sharing an already opened
* committed datatype */
if(!reopened_fo) {
/* Copy parent information */
if(old_dt->shared->parent)
- new_dt->shared->parent = H5T_copy(old_dt->shared->parent, method);
+ if(NULL == (new_dt->shared->parent = (*copyfn)(old_dt->shared->parent)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype's parent type")
switch(new_dt->shared->type) {
case H5T_COMPOUND:
@@ -3443,10 +3471,8 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
*/
/* Only malloc if space has been allocated for members - NAF */
if(new_dt->shared->u.compnd.nalloc > 0) {
- new_dt->shared->u.compnd.memb =
- (H5T_cmemb_t *)H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t));
- if (NULL == new_dt->shared->u.compnd.memb)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (new_dt->shared->u.compnd.memb = H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t))))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed")
H5MM_memcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t));
@@ -3456,15 +3482,17 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
unsigned j;
int old_match;
- s = new_dt->shared->u.compnd.memb[i].name;
- new_dt->shared->u.compnd.memb[i].name = H5MM_xstrdup(s);
- tmp = H5T_copy (old_dt->shared->u.compnd.memb[i].type, method);
+ if(NULL == (s = H5MM_xstrdup(new_dt->shared->u.compnd.memb[i].name)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy string for compound field's name")
+ new_dt->shared->u.compnd.memb[i].name = s;
+ if(NULL == (tmp = (*copyfn)(old_dt->shared->u.compnd.memb[i].type)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy compound field's datatype")
new_dt->shared->u.compnd.memb[i].type = tmp;
HDassert(tmp != NULL);
/* Range check against compound member's offset */
- if ((accum_change < 0) && ((ssize_t) new_dt->shared->u.compnd.memb[i].offset < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype")
+ if((accum_change < 0) && ((ssize_t) new_dt->shared->u.compnd.memb[i].offset < accum_change))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
/* Apply the accumulated size change to the offset of the field */
new_dt->shared->u.compnd.memb[i].offset += (size_t) accum_change;
@@ -3479,7 +3507,7 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
/* check if we couldn't find a match */
if(old_match < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "fields in datatype corrupted")
} /* end if */
else
old_match = (int) i;
@@ -3494,8 +3522,8 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
} /* end for */
/* Range check against datatype size */
- if ((accum_change < 0) && ((ssize_t) new_dt->shared->size < accum_change))
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid field size in datatype")
+ if((accum_change < 0) && ((ssize_t) new_dt->shared->size < accum_change))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
/* Apply the accumulated size change to the size of the compound struct */
new_dt->shared->size += (size_t) accum_change;
@@ -3508,27 +3536,25 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
* of each new member with copied values. That is, H5T_copy() is a
* deep copy.
*/
- new_dt->shared->u.enumer.name =
- (char **)H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char*));
- new_dt->shared->u.enumer.value =
- (uint8_t *)H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size);
- if(NULL == new_dt->shared->u.enumer.value)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (new_dt->shared->u.enumer.name = H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char*))))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam name array memory allocation failed")
+ if(NULL == (new_dt->shared->u.enumer.value = H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam value array memory allocation failed")
H5MM_memcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
for(i = 0; i < new_dt->shared->u.enumer.nmembs; i++) {
- s = old_dt->shared->u.enumer.name[i];
- new_dt->shared->u.enumer.name[i] = H5MM_xstrdup(s);
+ if(NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i])))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy string for enum value's name")
+ new_dt->shared->u.enumer.name[i] = s;
} /* end for */
break;
case H5T_VLEN:
case H5T_REFERENCE:
- if(method == H5T_COPY_TRANSIENT || method == H5T_COPY_REOPEN) {
+ if(set_memory_type)
/* H5T_copy converts any type into a memory type */
if(H5T_set_loc(new_dt, NULL, H5T_LOC_MEMORY) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
- } /* end if */
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
break;
case H5T_OPAQUE:
@@ -3540,7 +3566,7 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
case H5T_ARRAY:
/* Re-compute the array's size, in case it's base type changed size */
- new_dt->shared->size=new_dt->shared->u.array.nelem*new_dt->shared->parent->shared->size;
+ new_dt->shared->size = new_dt->shared->u.array.nelem * new_dt->shared->parent->shared->size;
break;
case H5T_NO_CLASS:
@@ -3559,15 +3585,15 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
* type and the new type is also named.
*/
if(H5O_loc_reset(&new_dt->oloc) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to initialize location")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location")
if(H5G_name_reset(&new_dt->path) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset path")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path")
if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
- if(H5O_loc_copy(&(new_dt->oloc), &(old_dt->oloc), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location")
+ if(H5O_loc_copy_deep(&(new_dt->oloc), &(old_dt->oloc)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy object location")
if(H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to copy path")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy path")
} /* end if */
/* Copy shared location information if the new type is named or if it is
@@ -3576,28 +3602,194 @@ H5T_copy(H5T_t *old_dt, H5T_copy_t method)
if((old_dt->sh_loc.type == H5O_SHARE_TYPE_SOHM || old_dt->sh_loc.type == H5O_SHARE_TYPE_HERE) ||
new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
if(H5O_set_shared(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy shared information")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy shared information")
} /* end if */
else
/* Reset shared component info */
H5O_msg_reset_share(H5O_DTYPE_ID, new_dt);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__complete_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_copy
+ *
+ * Purpose: Copies datatype OLD_DT. The resulting data type is not
+ * locked and is a transient type.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_DT argument.
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
+{
+ H5T_t *new_dt = NULL; /* New datatype */
+ H5T_copy_func_t copyfn; /* Pointer to correct copy routine */
+ H5T_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* check args */
+ HDassert(old_dt);
+
+ /* Allocate and copy core datatype information */
+ if(NULL == (new_dt = H5T__initiate_copy(old_dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info")
+
+ /* Check what sort of copy we are making */
+ switch (method) {
+ case H5T_COPY_TRANSIENT:
+ /*
+ * Return an unlocked transient type.
+ */
+ new_dt->shared->state = H5T_STATE_TRANSIENT;
+ copyfn = H5T__copy_transient;
+ break;
+
+ case H5T_COPY_ALL:
+ /*
+ * Return a transient type (locked or unlocked) or an unopened named
+ * type. Immutable transient types are degraded to read-only.
+ */
+ if(H5T_STATE_OPEN==old_dt->shared->state)
+ new_dt->shared->state = H5T_STATE_NAMED;
+ else if(H5T_STATE_IMMUTABLE==old_dt->shared->state)
+ new_dt->shared->state = H5T_STATE_RDONLY;
+ copyfn = H5T__copy_all;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type")
+ } /* end switch */
+
+ /* Finish making the copy of the datatype */
+ if(H5T__complete_copy(new_dt, old_dt, NULL, (method == H5T_COPY_TRANSIENT), copyfn) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization")
+
/* Set return value */
ret_value = new_dt;
done:
- if(ret_value == NULL) {
+ if(ret_value == NULL)
if(new_dt) {
- if(new_dt->shared)
- new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
+ HDassert(new_dt->shared);
+ new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
new_dt = H5FL_FREE(H5T_t, new_dt);
} /* end if */
- } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_copy() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_copy_reopen
+ *
+ * Purpose: Copy a datatype, possibly reopening a named datatype, as part
+ * the const-correct datatype copying routines.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_DT argument.
+ * Failure: NULL
+ *
+ * Programmer: David Young
+ * January 18, 2020
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5T_copy_reopen(H5T_t *old_dt)
+{
+ H5T_t *new_dt = NULL; /* New datatype */
+ H5T_shared_t *reopened_fo = NULL; /* Pointer to reopened existing named datatype */
+ H5T_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* check args */
+ HDassert(old_dt);
+
+ /* Allocate and copy core datatype information */
+ if(NULL == (new_dt = H5T__initiate_copy(old_dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info")
+
+ /*
+ * Return a transient type (locked or unlocked) or an opened named
+ * type. Immutable transient types are degraded to read-only.
+ */
+ if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
+ /* Check if the object is already open */
+ if(NULL == (reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) {
+ /* Clear any errors from H5FO_opened() */
+ H5E_clear_stack(NULL);
+
+ /* Open named datatype again */
+ if(H5O_open(&old_dt->oloc) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type")
+
+ /* Insert opened named datatype into opened object list for the file */
+ if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects")
+
+ /* Increment object count for the object in the top file */
+ if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
+
+ new_dt->shared->fo_count = 1;
+ } /* end if */
+ else {
+ /* The object is already open. Free the H5T_shared_t struct
+ * we had been using and use the one that already exists.
+ * Not terribly efficient. */
+ new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
+ new_dt->shared = reopened_fo;
+
+ reopened_fo->fo_count++;
+
+ /* Check if the object has been opened through the top file yet */
+ if(H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) {
+ /* Open the object through this top file */
+ if(H5O_open(&old_dt->oloc) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header")
+ } /* end if */
+
+ /* Increment object count for the object in the top file */
+ if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
+ } /* end else */
+
+ /* Set state for new datatype */
+ new_dt->shared->state = H5T_STATE_OPEN;
+ } /* end if */
+ else
+ /* Downgrade immutable datatypes to read-only */
+ if(H5T_STATE_IMMUTABLE == old_dt->shared->state)
+ new_dt->shared->state = H5T_STATE_RDONLY;
+
+ /* Finish making the copy of the datatype */
+ if(H5T__complete_copy(new_dt, old_dt, reopened_fo, TRUE, H5T_copy_reopen) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization")
+
+ /* Set return value */
+ ret_value = new_dt;
+
+done:
+ if(ret_value == NULL)
+ if(new_dt) {
+ HDassert(new_dt->shared);
+ new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
+ new_dt = H5FL_FREE(H5T_t, new_dt);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_copy_reopen() */
+
/*-------------------------------------------------------------------------
* Function: H5T_lock
*