summaryrefslogtreecommitdiffstats
path: root/src/H5Tcompound.c
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2009-10-27 22:23:49 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2009-10-27 22:23:49 (GMT)
commit376a788840fe6db1f253a371e3bcde527b4bfd3f (patch)
tree5aff621b28ab1ff02f41b1ea83325b11d287d13f /src/H5Tcompound.c
parent597739142f65d71f1ccf9eeeda6568b147e506b5 (diff)
downloadhdf5-376a788840fe6db1f253a371e3bcde527b4bfd3f.zip
hdf5-376a788840fe6db1f253a371e3bcde527b4bfd3f.tar.gz
hdf5-376a788840fe6db1f253a371e3bcde527b4bfd3f.tar.bz2
[svn-r17760] Purpose: Fix problem with H5TB API
Description: The H5TB API makes some improper assumptions about the order of compound datatype members. Namely, it assumes that members remain in the order in which they were inserted. Unfortunately, this assumption is inherent in the design of the interface. The library has been patched so that this assumption holds in situations relevant to H5TB. Tested: jam, linew, amani (h5committest)
Diffstat (limited to 'src/H5Tcompound.c')
-rw-r--r--src/H5Tcompound.c203
1 files changed, 66 insertions, 137 deletions
diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c
index 02d6bd1..db7a701b 100644
--- a/src/H5Tcompound.c
+++ b/src/H5Tcompound.c
@@ -45,11 +45,6 @@
/******************/
/* Local Typedefs */
/******************/
-/* "Key" (+ user data) for bsearch callback */
-typedef struct{
- size_t offset; /* Offset of member to be added */
- const H5T_cmemb_t *max_under; /* Member with maximum offset seen that is not above "offset" */
-} H5T_insert_compar_t;
/********************/
@@ -421,48 +416,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5T_insert_compar
- *
- * Purpose: Callback function for bsearch called from H5T_insert.
- * Reports whether obj has a lower of higher offset than
- * that stored in key. Also keeps track of the highest
- * offset seen that is not higher than that in key.
- *
- * Return: -1 if key < obj
- * 0 if key == obj
- * 1 if key > obj
- *
- * Programmer: Neil Fortner
- * Wednesday, January 7, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5T_insert_compar(const void *_key, const void *_obj)
-{
- H5T_insert_compar_t *key = *(H5T_insert_compar_t * const *)_key; /* User data */
- const H5T_cmemb_t *memb = (const H5T_cmemb_t *)_obj; /* Compound member being examined */
- int ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_insert_compar)
-
- if(key->offset > memb->offset) {
- if(key->max_under == NULL || memb->offset > key->max_under->offset)
- key->max_under = memb;
- ret_value = 1;
- } /* end if */
- else if(key->offset < memb->offset)
- ret_value = -1;
- else
- ret_value = 0; /* Should not happen */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_insert_compar() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5T_insert
*
* Purpose: Adds a new MEMBER to the compound datatype PARENT. The new
@@ -482,8 +435,6 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
{
unsigned idx; /* Index of member to insert */
size_t total_size;
- H5T_insert_compar_t key; /* Key for bsearch compare function */
- H5T_insert_compar_t *keyptr = &key; /* Pointer to key */
unsigned i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -500,39 +451,20 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
if(!HDstrcmp(parent->shared->u.compnd.memb[i].name, name))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member name is not unique")
+ /* Does the new member overlap any existing member ? */
total_size = member->shared->size;
+ for(i = 0; i < parent->shared->u.compnd.nmembs; i++)
+ if((offset <= parent->shared->u.compnd.memb[i].offset &&
+ (offset + total_size) > parent->shared->u.compnd.memb[i].offset) ||
+ (parent->shared->u.compnd.memb[i].offset <= offset &&
+ (parent->shared->u.compnd.memb[i].offset +
+ parent->shared->u.compnd.memb[i].size) > offset))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member")
/* Does the new member overlap the end of the compound type? */
if((offset + total_size) > parent->shared->size)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member extends past end of compound type")
- if(parent->shared->u.compnd.sorted != H5T_SORT_VALUE)
- if(H5T_sort_value(parent, NULL) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOMPARE, FAIL, "value sort failed")
-
- /* Find the position to insert the new member */
- if(parent->shared->u.compnd.nmembs == 0)
- idx = 0;
- else {
- /* Key value (including user data) for compar callback */
- key.offset = offset;
- key.max_under = NULL;
-
- /* Do a binary search on the offsets of the (now sorted) members. We do
- * not expect to find an exact match (if we do it is an error), rely on
- * the user data in the key to keep track of the closest member below
- * the new member. */
- if(NULL != HDbsearch(&keyptr, parent->shared->u.compnd.memb, parent->shared->u.compnd.nmembs,
- sizeof(parent->shared->u.compnd.memb[0]), H5T_insert_compar))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member")
- idx = (key.max_under == NULL) ? 0 : (unsigned) (key.max_under - parent->shared->u.compnd.memb + 1);
- } /* end else */
-
- /* Does the new member overlap any existing member ? */
- if((idx < parent->shared->u.compnd.nmembs && (offset + total_size) > parent->shared->u.compnd.memb[idx].offset) ||
- (idx && (parent->shared->u.compnd.memb[idx-1].offset + parent->shared->u.compnd.memb[idx-1].size) > offset))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member")
-
/* Increase member array if necessary */
if(parent->shared->u.compnd.nmembs >= parent->shared->u.compnd.nalloc) {
unsigned na = MAX(1, parent->shared->u.compnd.nalloc * 2);
@@ -544,68 +476,23 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
parent->shared->u.compnd.memb = x;
} /* end if */
- /* Determine if the compound datatype stays packed */
- if(parent->shared->u.compnd.packed) {
- /* Check if the member type is packed */
- if(H5T_is_packed(member) > 0) {
- if(idx == 0) {
- /* If the is the first member, the datatype is not packed
- * if the first member isn't at offset 0
- */
- if(offset > 0)
- parent->shared->u.compnd.packed = FALSE;
- } /* end if */
- else {
- /* If the is not the first member, the datatype is not
- * packed if the new member isn't adjoining the previous member
- */
- if(offset != (parent->shared->u.compnd.memb[idx - 1].offset + parent->shared->u.compnd.memb[idx - 1].size))
- parent->shared->u.compnd.packed = FALSE;
- } /* end else */
- } /* end if */
- else
- parent->shared->u.compnd.packed = FALSE;
- } /* end if */
- else
- /* Check if inserting this member causes the parent to become packed */
- /* First check if it completely closes a gap */
- /* No need to check if it's being appended to the end */
- if(idx != parent->shared->u.compnd.nmembs
- && (offset + total_size) == parent->shared->u.compnd.memb[idx].offset
- && (idx == 0 ? offset == 0 : (parent->shared->u.compnd.memb[idx-1].offset
- + parent->shared->u.compnd.memb[idx-1].size) == offset)
- && H5T_is_packed(member) > 0) {
-
- /* Start out packed */
- parent->shared->u.compnd.packed = TRUE;
-
- /* Check if the entire type is now packed */
- if((idx != 0 && parent->shared->u.compnd.memb[0].offset != 0)
- || !H5T_is_packed(parent->shared->u.compnd.memb[0].type))
- parent->shared->u.compnd.packed = FALSE;
- else
- for(i = 1; i < parent->shared->u.compnd.nmembs; i++)
- if((i != idx && parent->shared->u.compnd.memb[i].offset
- != (parent->shared->u.compnd.memb[i - 1].offset
- + parent->shared->u.compnd.memb[i - 1].size))
- || !H5T_is_packed(parent->shared->u.compnd.memb[i].type)) {
- parent->shared->u.compnd.packed = FALSE;
- break;
- } /* end if */
- } /* end if */
-
- /* Reshape the memb array to accomodate the new member */
- if(idx != parent->shared->u.compnd.nmembs)
- HDmemmove(&parent->shared->u.compnd.memb[idx+1], &parent->shared->u.compnd.memb[idx],
- (parent->shared->u.compnd.nmembs - idx) * sizeof(parent->shared->u.compnd.memb[0]));
-
- /* Add member to member array */
+ /* Add member to end of member array */
+ idx = parent->shared->u.compnd.nmembs;
parent->shared->u.compnd.memb[idx].name = H5MM_xstrdup(name);
parent->shared->u.compnd.memb[idx].offset = offset;
parent->shared->u.compnd.memb[idx].size = total_size;
parent->shared->u.compnd.memb[idx].type = H5T_copy(member, H5T_COPY_ALL);
+ parent->shared->u.compnd.sorted = H5T_SORT_NONE;
parent->shared->u.compnd.nmembs++;
+ parent->shared->u.compnd.memb_size+=total_size;
+
+ /* It should not be possible to get this far if the type is already packed
+ * - the new member would overlap something */
+ HDassert(!(parent->shared->u.compnd.packed));
+
+ /* Determine if the compound datatype becomes packed */
+ H5T_update_packed(parent);
/* Set the "force conversion" flag if the field's datatype indicates */
if(member->shared->force_conv == TRUE)
@@ -730,13 +617,55 @@ H5T_is_packed(const H5T_t *dt)
/* If this is a compound datatype, check if it is packed */
if(dt->shared->type == H5T_COMPOUND) {
- H5T_compnd_t *compnd = &(dt->shared->u.compnd); /* Convenience pointer to compound info */
- ret_value = (htri_t)(compnd->packed && compnd->nmembs > 0
- && compnd->memb[compnd->nmembs - 1].offset
- + compnd->memb[compnd->nmembs - 1].size
- == dt->shared->size);
+ ret_value = (htri_t)(dt->shared->u.compnd.packed);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_is_packed() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_update_packed
+ *
+ * Purpose: Checks whether a datatype which is compound became packed
+ * after recent changes. This function does not assume that
+ * the status of the "packed" field is correct, and sets
+ * this field to the correct value.
+ *
+ * Return: void
+ *
+ * Programmer: Neil Fortner
+ * Monday, October 19, 2009
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5T_update_packed(const H5T_t *dt)
+{
+ unsigned i; /* Index */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_update_packed)
+
+ HDassert(dt);
+ HDassert(dt->shared->type == H5T_COMPOUND);
+
+ /* First check if all space is used in the "top level" type */
+ if(dt->shared->size == dt->shared->u.compnd.memb_size) {
+ /* Set the packed flag to TRUE */
+ dt->shared->u.compnd.packed = TRUE;
+
+ /* Now check if all members are packed */
+ for(i = 0; i < dt->shared->u.compnd.nmembs; i++)
+ if(!H5T_is_packed(dt->shared->u.compnd.memb[i].type)) {
+ dt->shared->u.compnd.packed = FALSE;
+ break;
+ } /* end if */
+ } /* end if */
+ else
+ dt->shared->u.compnd.packed = FALSE;
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5T_update_packed() */
+