summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5Odtype.c29
-rw-r--r--src/H5T.c14
-rw-r--r--src/H5Tcompound.c203
-rw-r--r--src/H5Tpkg.h2
-rw-r--r--test/cmpd_dset.c418
6 files changed, 390 insertions, 278 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 83c4814..cf5fea3 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -406,6 +406,8 @@ Bug Fixes since HDF5-1.8.0 release
High-Level APIs:
------
+ - Fixed a bug where the H5TB API would forget the order of fields when
+ added out of offset order. (NAF - 2009/10/27)
- H5DSis_attached failed to account for different platform types. Added a
get native type call. (ADB - 2009/9/29 - 1562)
- Dimension scales: The scale index return value in H5DSiterate_scales was not always
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index a9812690..fc71d65 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -269,9 +269,9 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
*/
dt->shared->u.compnd.nmembs = flags & 0xffff;
HDassert(dt->shared->u.compnd.nmembs > 0);
- dt->shared->u.compnd.packed = TRUE; /* Start off packed */
dt->shared->u.compnd.nalloc = dt->shared->u.compnd.nmembs;
dt->shared->u.compnd.memb = (H5T_cmemb_t *)H5MM_calloc(dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t));
+ dt->shared->u.compnd.memb_size = 0;
if(NULL == dt->shared->u.compnd.memb)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
@@ -385,6 +385,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Member size */
dt->shared->u.compnd.memb[i].size = temp_type->shared->size;
+ dt->shared->u.compnd.memb_size += temp_type->shared->size;
/* Set the field datatype (finally :-) */
dt->shared->u.compnd.memb[i].type = temp_type;
@@ -400,31 +401,11 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Update the maximum member position covered */
max_memb_pos = MAX(max_memb_pos, (dt->shared->u.compnd.memb[i].offset + dt->shared->u.compnd.memb[i].size));
-
- /* Check if the datatype stayed packed */
- if(dt->shared->u.compnd.packed) {
- /* Check if the member type is packed */
- if(H5T_is_packed(temp_type) > 0) {
- if(i == 0) {
- /* If the is the first member, the datatype is not packed
- * if the first member isn't at offset 0
- */
- if(dt->shared->u.compnd.memb[i].offset > 0)
- dt->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(dt->shared->u.compnd.memb[i].offset != (dt->shared->u.compnd.memb[i - 1].offset + dt->shared->u.compnd.memb[i - 1].size))
- dt->shared->u.compnd.packed = FALSE;
- } /* end else */
- } /* end if */
- else
- dt->shared->u.compnd.packed = FALSE;
- } /* end if */
} /* end for */
+ /* Check if the compound type is packed */
+ H5T_update_packed(dt);
+
/* Upgrade the compound if requested */
if(version < upgrade_to) {
version = upgrade_to;
diff --git a/src/H5T.c b/src/H5T.c
index 1e30f77..4041cd5 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -2976,8 +2976,8 @@ H5T_create(H5T_class_t type, size_t size)
dt->shared->type = type;
if(type==H5T_COMPOUND) {
- dt->shared->u.compnd.packed=TRUE; /* Start out packed */
- dt->shared->u.compnd.sorted=H5T_SORT_VALUE; /* Start out sorted by value */
+ dt->shared->u.compnd.packed=FALSE; /* Start out unpacked */
+ dt->shared->u.compnd.memb_size=0;
} /* end if */
else if(type==H5T_OPAQUE)
/* Initialize the tag in case it's not set later. A null tag will
@@ -3678,7 +3678,13 @@ H5T_set_size(H5T_t *dt, size_t size)
if(size<(max_offset+max_size))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size shrinking will cut off last member ");
+
+ /* Compound must not have been packed previously */
+ /* We will check if resizing changed the packed state of
+ * this type at the end of this function */
+ HDassert(!dt->shared->u.compnd.packed);
}
+
break;
case H5T_STRING:
@@ -3754,6 +3760,10 @@ H5T_set_size(H5T_t *dt, size_t size)
dt->shared->u.atomic.prec = prec;
}
} /* end if */
+
+ /* Check if the new compound type is packed */
+ if(dt->shared->type == H5T_COMPOUND)
+ H5T_update_packed(dt);
}
done:
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() */
+
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 18bf7cf..45b0e7f 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -307,6 +307,7 @@ typedef struct H5T_compnd_t {
H5T_sort_t sorted; /*how are members sorted? */
hbool_t packed; /*are members packed together? */
H5T_cmemb_t *memb; /*array of struct members */
+ size_t memb_size; /*total of all member sizes */
} H5T_compnd_t;
/* An enumeration datatype */
@@ -1388,6 +1389,7 @@ H5_DLL herr_t H5T_insert(H5T_t *parent, const char *name, size_t offset,
const H5T_t *member);
H5_DLL size_t H5T_get_member_size(const H5T_t *dt, unsigned membno);
H5_DLL htri_t H5T_is_packed(const H5T_t *dt);
+H5_DLL void H5T_update_packed(const H5T_t *dt);
H5_DLL H5T_subset_info_t *H5T_conv_struct_subset(const H5T_cdata_t *cdata);
/* Enumerated type functions */
diff --git a/test/cmpd_dset.c b/test/cmpd_dset.c
index 167e6a1..b154f51 100644
--- a/test/cmpd_dset.c
+++ b/test/cmpd_dset.c
@@ -1750,7 +1750,8 @@ error:
* Function: test_pack_ooo
*
* Purpose: Test inserting fields into a compound out of offset order.
- * Verifies that the compound
+ * Verifies that the compound is correctly marked as packed
+ * or non-packed.
*
* Return: Success: 0
*
@@ -1772,6 +1773,8 @@ test_pack_ooo(void)
unsigned num_free; /* Number of free slots in order */
unsigned sub_cmpd_order; /* Order to insert the inner compound */
char name[6]; /* Member name */
+ unsigned extra_space; /* Whether to add extra space to the end of
+ * the compound */
unsigned i, j; /* Indices */
HDsrand((unsigned) time(NULL));
@@ -1799,171 +1802,353 @@ test_pack_ooo(void)
/* Generate order to insert inner compound type */
sub_cmpd_order = HDrand() % PACK_NMEMBS;
- TESTING("random member insertion with empty compound subtype");
+ for(extra_space=0; extra_space<2; extra_space ++) {
+ if(extra_space)
+ puts("With extra space at the end of compound...");
+ else
+ puts("Without extra space at the end of compound...");
- /* Create inner compound type. It will be empty for the first run */
- if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
+ TESTING("random member insertion with empty compound subtype");
- /* Create main compound type, with extra space at the end */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Create inner compound type. It will be empty for the first run */
+ if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
- /* Insert the compound members in the random order previously generated */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == sub_cmpd_order) {
- if(H5Tinsert(cmpd, name, 4 * order[i], sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * order[i], H5T_STD_I32BE) < 0) PACK_OOO_ERROR
- } /* end for */
+ /* Create main compound type, with extra space at the end */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
- /* Verify that the compound is not packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ /* Insert the compound members in the random order previously generated */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == sub_cmpd_order) {
+ if(H5Tinsert(cmpd, name, 4 * order[i], sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * order[i], H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
- /* Close the main compound */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
- PASSED();
+ /* Close the main compound */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
- TESTING("random member insertion with full compound subtype");
+ PASSED();
- /* Complete the inner compound type */
- if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
+ TESTING("random member insertion with full compound subtype");
- /* Recreate main compound type */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Complete the inner compound type */
+ if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
- /* Insert the compound members in the random order previously generated */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == sub_cmpd_order) {
- if(H5Tinsert(cmpd, name, 4 * order[i], sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * order[i], H5T_STD_I32BE) < 0) PACK_OOO_ERROR
- } /* end for */
+ /* Recreate main compound type */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
- /* Verify that the compound is packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(!dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ /* Insert the compound members in the random order previously generated */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == sub_cmpd_order) {
+ if(H5Tinsert(cmpd, name, 4 * order[i], sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * order[i], H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
- /* Close */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
- if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed != !extra_space) PACK_OOO_ERROR
- PASSED();
+ /* Close */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
- TESTING("reverse member insertion with empty compound subtype");
+ PASSED();
- /* Create inner compound type. It will be empty for the first run */
- if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
+ TESTING("reverse member insertion with empty compound subtype");
- /* Create main compound type, with extra space at the end */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Create inner compound type. It will be empty for the first run */
+ if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
- /* Insert the compound members in reverse order, with compound last */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == PACK_NMEMBS - 1) {
- if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), H5T_STD_I32BE) < 0) PACK_OOO_ERROR
- } /* end for */
+ /* Create main compound type, with extra space at the end */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
- /* Verify that the compound is not packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ /* Insert the compound members in reverse order, with compound last */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == PACK_NMEMBS - 1) {
+ if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
- /* Close the main compound */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
- PASSED();
+ /* Close the main compound */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
- TESTING("reverse member insertion with full compound subtype");
+ PASSED();
- /* Complete the inner compound type */
- if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
+ TESTING("reverse member insertion with full compound subtype");
- /* Recreate main compound type */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Complete the inner compound type */
+ if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
- /* Insert the compound members in reverse order, with compound last */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == PACK_NMEMBS - 1) {
- if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), H5T_STD_I32BE) < 0) PACK_OOO_ERROR
- } /* end for */
+ /* Recreate main compound type */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
- /* Verify that the compound is packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(!dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ /* Insert the compound members in reverse order, with compound last */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == PACK_NMEMBS - 1) {
+ if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * (PACK_NMEMBS - i - 1), H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
- /* Close */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
- if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
+ /* Verify that the compound is packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed != !extra_space) PACK_OOO_ERROR
- PASSED();
+ /* Close */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
- TESTING("forward member insertion with empty compound subtype");
+ PASSED();
- /* Create inner compound type. It will be empty for the first run */
- if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
+ TESTING("forward member insertion with empty compound subtype");
- /* Create main compound type, with extra space at the end */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Create inner compound type. It will be empty for the first run */
+ if((sub_cmpd = H5Tcreate(H5T_COMPOUND, 4)) < 0) PACK_OOO_ERROR
- /* Insert the compound members in forward order, with compound first */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == 0) {
- if(H5Tinsert(cmpd, name, 4 * i, sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * i, H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ /* Create main compound type, with extra space at the end */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
+
+ /* Insert the compound members in forward order, with compound first */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == 0) {
+ if(H5Tinsert(cmpd, name, 4 * i, sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * i, H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
+
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
+
+ /* Close the main compound */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+
+ PASSED();
+
+ TESTING("forward member insertion with full compound subtype");
+
+ /* Complete the inner compound type */
+ if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
+
+ /* Recreate main compound type */
+ if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + extra_space)) < 0) PACK_OOO_ERROR
+
+ /* Insert the compound members in forward order */
+ for(i=0; i<PACK_NMEMBS; i++) {
+ sprintf(name, "%05d", i);
+ if(i == 0) {
+ if(H5Tinsert(cmpd, name, 4 * i, sub_cmpd) < 0) PACK_OOO_ERROR
+ } else
+ if(H5Tinsert(cmpd, name, 4 * i, H5T_STD_I32BE) < 0) PACK_OOO_ERROR
+ } /* end for */
+
+ /* Verify that the compound is packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
+ if(dt->shared->u.compnd.packed != !extra_space) PACK_OOO_ERROR
+
+ /* Close */
+ if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
+
+ PASSED();
} /* end for */
+ return 0;
+
+error:
+ puts("*** DATASET TESTS FAILED ***");
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_ooo_order
+ *
+ * Purpose: Test inserting fields into a compound out of offset order.
+ * Verifies that the order of compound members is the same as
+ * the order in which they were inserted. While this is
+ * explicitly not guaranteed by the documentation, the H5TB
+ * API currently makes this assumption.
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Neil Fortner
+ * Monday, 19 October 2009
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+static int
+test_ooo_order(char *filename)
+{
+ hid_t file; /* File ID */
+ hid_t dtype, dtype_tmp; /* Datatype IDs */
+ H5T_t *dt; /* Datatype pointer */
+
+ TESTING("that compound member insertion order is preserved")
+
+ /* Create the file */
+ if ((file = H5Fcreate (filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Create the compound */
+ if((dtype = H5Tcreate(H5T_COMPOUND, 20)) < 0) TEST_ERROR
+ if(H5Tinsert(dtype, "A", 8, H5T_STD_I32LE) < 0) TEST_ERROR
+ if(H5Tinsert(dtype, "B", 12, H5T_STD_I32LE) < 0) TEST_ERROR
+ if(H5Tinsert(dtype, "C", 0, H5T_STD_I32LE) < 0) TEST_ERROR
+ if(H5Tinsert(dtype, "D", 16, H5T_STD_I32LE) < 0) TEST_ERROR
+
/* Verify that the compound is not packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(dt->shared->u.compnd.packed) TEST_ERROR
- /* Close the main compound */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
+ /* Verify that the order is the same as the insertion order */
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
- PASSED();
+ /* Commit the datatype */
+ if(H5Tcommit2(file, "dtype", dtype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR
- TESTING("forward member insertion with full compound subtype");
+ /* Close and reopen the file */
+ if(H5Tclose(dtype)) TEST_ERROR
+ if(H5Fclose(file)) TEST_ERROR
+ if((file = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR
- /* Complete the inner compound type */
- if(H5Tinsert(sub_cmpd, "int", 0, H5T_STD_I32LE) < 0) PACK_OOO_ERROR
+ /* Open the type */
+ if((dtype_tmp = H5Topen2(file, "dtype", H5P_DEFAULT)) < 0) TEST_ERROR
- /* Recreate main compound type */
- if((cmpd = H5Tcreate(H5T_COMPOUND, (4 * PACK_NMEMBS) + 1)) < 0) PACK_OOO_ERROR
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype_tmp, H5I_DATATYPE)))
+ TEST_ERROR
+ if(dt->shared->u.compnd.packed) TEST_ERROR
- /* Insert the compound members in forward order */
- for(i=0; i<PACK_NMEMBS; i++) {
- sprintf(name, "%05d", i);
- if(i == 0) {
- if(H5Tinsert(cmpd, name, 4 * i, sub_cmpd) < 0) PACK_OOO_ERROR
- } else
- if(H5Tinsert(cmpd, name, 4 * i, H5T_STD_I32BE) < 0) PACK_OOO_ERROR
- } /* end for */
+ /* Verify that the order is the same as the insertion order */
+ if(H5Tget_member_offset(dtype_tmp, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 3) != 16) TEST_ERROR
+
+ /* Copy the datatype */
+ if((dtype = H5Tcopy(dtype_tmp)) < 0) TEST_ERROR
+
+ /* Verify that the compound is not packed */
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(dt->shared->u.compnd.packed) TEST_ERROR
+
+ /* Verify that the order is the same as the insertion order */
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
+
+ /* Insert the last member */
+ if(H5Tinsert(dtype, "E", 4, H5T_STD_I32LE) < 0) TEST_ERROR
/* Verify that the compound is packed */
- if(NULL == (dt = (H5T_t *) H5I_object_verify(cmpd, H5I_DATATYPE))) PACK_OOO_ERROR
- if(!dt->shared->u.compnd.packed) PACK_OOO_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(!dt->shared->u.compnd.packed) TEST_ERROR
+
+ /* Verify that the order is the same as the insertion order */
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 4) != 4) TEST_ERROR
+
+ /* Commit the modified datatype */
+ if(H5Tcommit2(file, "dtype2", dtype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close and reopen the file */
+ if(H5Tclose(dtype_tmp)) TEST_ERROR
+ if(H5Tclose(dtype)) TEST_ERROR
+ if(H5Fclose(file)) TEST_ERROR
+ if((file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Open the type, and verify status */
+ if((dtype_tmp = H5Topen2(file, "dtype2", H5P_DEFAULT)) < 0) TEST_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype_tmp, H5I_DATATYPE)))
+ TEST_ERROR
+ if(!dt->shared->u.compnd.packed) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 3) != 16) TEST_ERROR
+ if(H5Tget_member_offset(dtype_tmp, 4) != 4) TEST_ERROR
+
+ /* Copy the datatype, and verify status */
+ if((dtype = H5Tcopy(dtype_tmp)) < 0) TEST_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(!dt->shared->u.compnd.packed) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 4) != 4) TEST_ERROR
+
+ /* Expand the type, and verify that it became unpacked */
+ if(H5Tset_size(dtype, 21) < 0) TEST_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(dt->shared->u.compnd.packed) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 4) != 4) TEST_ERROR
+
+ /* Shrink the type, and verify that it became packed */
+ if(H5Tset_size(dtype, 20) < 0) TEST_ERROR
+ if(NULL == (dt = (H5T_t *) H5I_object_verify(dtype, H5I_DATATYPE)))
+ TEST_ERROR
+ if(!dt->shared->u.compnd.packed) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 0) != 8) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 1) != 12) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 2) != 0) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 3) != 16) TEST_ERROR
+ if(H5Tget_member_offset(dtype, 4) != 4) TEST_ERROR
/* Close */
- if(H5Tclose(cmpd) < 0) PACK_OOO_ERROR
- if(H5Tclose(sub_cmpd) < 0) PACK_OOO_ERROR
+ if(H5Tclose(dtype_tmp)) TEST_ERROR
+ if(H5Tclose(dtype)) TEST_ERROR
+ if(H5Fclose(file)) TEST_ERROR
PASSED();
-
return 0;
error:
+ H5E_BEGIN_TRY {
+ H5Tclose(dtype_tmp);
+ H5Tclose(dtype);
+ H5Fclose(file);
+ } H5E_END_TRY
puts("*** DATASET TESTS FAILED ***");
return 1;
-}
+} /* test_ooo_order */
/*-------------------------------------------------------------------------
@@ -2019,6 +2204,9 @@ main (int argc, char *argv[])
puts("Testing that compound types can be packed out of order:");
nerrors += test_pack_ooo();
+ puts("Testing compound member ordering:");
+ nerrors += test_ooo_order(fname);
+
if (nerrors) {
printf("***** %u FAILURE%s! *****\n",
nerrors, 1==nerrors?"":"S");