summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-09-12 04:36:23 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-09-12 04:36:23 (GMT)
commitf3e445cfcb4573ce87212cf7046a3f67f36d616f (patch)
tree3e75cee494b31453d15f66c02d10922b4c10eea1
parent75471825fde4e55fb23cda381563372bc91795e1 (diff)
downloadhdf5-f3e445cfcb4573ce87212cf7046a3f67f36d616f.zip
hdf5-f3e445cfcb4573ce87212cf7046a3f67f36d616f.tar.gz
hdf5-f3e445cfcb4573ce87212cf7046a3f67f36d616f.tar.bz2
[svn-r7469] Purpose:
Code cleanup, etc. Description: Generalize Ray's datatype fixes to handle packing compound datatypes which are the base type of an array or variable-length type, etc. Also track "packedness" of a compound datatype from it's creation, instead of only setting the 'packed' flag after the datatype was explicitly packed. Updated docs to reflect that a compound datatype is allowed to grow (but not shrink). Platforms tested: FreeBSD 4.9 (sleipnir) h5committest
-rw-r--r--doc/html/RM_H5T.html8
-rw-r--r--release_docs/RELEASE.txt3
-rw-r--r--src/H5Odtype.c24
-rw-r--r--src/H5T.c10
-rw-r--r--src/H5Tcompound.c122
-rw-r--r--src/H5Tpkg.h9
-rw-r--r--test/dtypes.c183
7 files changed, 328 insertions, 31 deletions
diff --git a/doc/html/RM_H5T.html b/doc/html/RM_H5T.html
index a877ff5..7895b71 100644
--- a/doc/html/RM_H5T.html
+++ b/doc/html/RM_H5T.html
@@ -1071,15 +1071,15 @@ H5Tget_overflow ()
<dd>Sets the total size for an atomic datatype.
<dt><strong>Description:</strong>
<dd><code>H5Tset_size</code> sets the total size in bytes,
- <code>size</code>, for an atomic datatype (this operation
- is not permitted on compound datatypes). If the size is
- decreased so that the significant bits of the datatype extend beyond
+ <code>size</code>, for a datatype. If the datatype is atomic and size
+ is decreased so that the significant bits of the datatype extend beyond
the edge of the new size, then the `offset' property is decreased
toward zero. If the `offset' becomes zero and the significant
bits of the datatype still hang over the edge of the new size, then
the number of significant bits is decreased.
Adjusting the size of an H5T_STRING automatically sets the precision
- to 8*size. All datatypes have a positive size.
+ to 8*size. A compound datatype may increase in size, but may not
+ shrink. All datatypes must have a positive size.
<dt><strong>Parameters:</strong>
<dl>
<dt><em>hid_t</em> <code>type_id</code>
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 51c34ee..19931e1 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -56,6 +56,9 @@ Bug Fixes since HDF5-1.6.0 release
Library
-------
+ - Allow compound datatypes to grow in size. SLU - 2003/09/10
+ - Detect if a type is already packed before attempting to pack it
+ again or check if it is locked. SLU - 2003/09/10
- Corrected bug when opening a file twice with read-only permission
for one open and then closing the read-only access file ID would
generate an error. QAK - 2003/09/10
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 849e0b9..934c113 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -187,6 +187,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
*/
dt->u.compnd.nmembs = flags & 0xffff;
assert(dt->u.compnd.nmembs > 0);
+ dt->u.compnd.packed = TRUE; /* Start off packed */
dt->u.compnd.nalloc = dt->u.compnd.nmembs;
dt->u.compnd.memb = H5MM_calloc(dt->u.compnd.nalloc*
sizeof(H5T_cmemb_t));
@@ -278,6 +279,29 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Set the field datatype (finally :-) */
dt->u.compnd.memb[i].type=temp_type;
+
+ /* Check if the datatype stayed packed */
+ if(dt->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->u.compnd.memb[i].offset>0)
+ dt->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->u.compnd.memb[i].offset!=(dt->u.compnd.memb[i-1].offset+dt->u.compnd.memb[i-1].size))
+ dt->u.compnd.packed=FALSE;
+ } /* end else */
+ } /* end if */
+ else
+ dt->u.compnd.packed=FALSE;
+ } /* end if */
}
break;
diff --git a/src/H5T.c b/src/H5T.c
index 13f57a2..f27a8f0 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -2660,7 +2660,7 @@ H5Tset_size(hid_t type_id, size_t size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive");
if (size == H5T_VARIABLE && dt->type!=H5T_STRING)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length");
- if ((H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) || (H5T_COMPOUND==dt->type && dt->u.compnd.nmembs>0))
+ if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined");
if (H5T_REFERENCE==dt->type)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
@@ -3334,6 +3334,8 @@ H5T_create(H5T_class_t type, size_t size)
if (NULL==(dt = H5FL_CALLOC(H5T_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
dt->type = type;
+ if(type==H5T_COMPOUND)
+ dt->u.compnd.packed=TRUE; /* Start out packed */
break;
case H5T_ENUM:
@@ -4014,10 +4016,14 @@ H5T_set_size(H5T_t *dt, size_t size)
case H5T_TIME:
case H5T_BITFIELD:
case H5T_OPAQUE:
- case H5T_COMPOUND:
/* nothing to check */
break;
+ case H5T_COMPOUND:
+ if(size<dt->size)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "can't shrink compound datatype");
+ break;
+
case H5T_STRING:
/* Convert string to variable-length datatype */
if(size==H5T_VARIABLE) {
diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c
index 790de46..a1c93a1 100644
--- a/src/H5Tcompound.c
+++ b/src/H5Tcompound.c
@@ -356,10 +356,8 @@ H5Tpack(hid_t type_id)
H5TRACE1("e","i",type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type)
+ if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_detect_class(dt,H5T_COMPOUND)<=0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type");
- if (H5T_STATE_TRANSIENT!=dt->state)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data type is read-only");
/* Pack */
if (H5T_pack(dt) < 0)
@@ -446,6 +444,29 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
parent->u.compnd.sorted = H5T_SORT_NONE;
parent->u.compnd.nmembs++;
+ /* Determine if the compound datatype stayed packed */
+ if(parent->u.compnd.packed) {
+ /* Check if the member type is packed */
+ if(H5T_is_packed(parent->u.compnd.memb[idx].type)>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(parent->u.compnd.memb[idx].offset>0)
+ parent->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(parent->u.compnd.memb[idx].offset!=(parent->u.compnd.memb[idx-1].offset+parent->u.compnd.memb[idx-1].size))
+ parent->u.compnd.packed=FALSE;
+ } /* end else */
+ } /* end if */
+ else
+ parent->u.compnd.packed=FALSE;
+ } /* end if */
+
/*
* Set the "force conversion" flag if the field's datatype indicates
*/
@@ -479,31 +500,88 @@ H5T_pack(H5T_t *dt)
size_t offset;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_pack, FAIL);
+ FUNC_ENTER_NOINIT(H5T_pack);
assert(dt);
- if (H5T_COMPOUND == dt->type) {
- assert(H5T_STATE_TRANSIENT==dt->state);
+ if(H5T_detect_class(dt,H5T_COMPOUND)>0) {
+ /* If datatype has been packed, skip packing it and indicate success */
+ if(H5T_is_packed(dt)== TRUE)
+ HGOTO_DONE(SUCCEED);
+
+ /* Check for packing unmodifiable datatype */
+ if (H5T_STATE_TRANSIENT!=dt->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is read-only");
- /* Recursively pack the members */
- for (i=0; i<dt->u.compnd.nmembs; i++) {
- if (H5T_pack(dt->u.compnd.memb[i].type) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound data type");
- }
-
- /* Remove padding between members */
- H5T_sort_value(dt, NULL);
- for (i=0, offset=0; i<dt->u.compnd.nmembs; i++) {
- dt->u.compnd.memb[i].offset = offset;
- offset += dt->u.compnd.memb[i].size;
- }
-
- /* Change total size */
- dt->size = MAX(1, offset);
- }
+ if(dt->parent) {
+ if (H5T_pack(dt->parent) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack parent of datatype");
+
+ /* Adjust size of datatype appropriately */
+ if(dt->type==H5T_ARRAY)
+ dt->size = dt->parent->size * dt->u.array.nelem;
+ else if(dt->type!=H5T_VLEN)
+ dt->size = dt->parent->size;
+ } /* end if */
+ else if(dt->type==H5T_COMPOUND) {
+ /* Recursively pack the members */
+ for (i=0; i<dt->u.compnd.nmembs; i++)
+ if (H5T_pack(dt->u.compnd.memb[i].type) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound data type");
+
+ /* Remove padding between members */
+ H5T_sort_value(dt, NULL);
+ for (i=0, offset=0; i<dt->u.compnd.nmembs; i++) {
+ dt->u.compnd.memb[i].offset = offset;
+ offset += dt->u.compnd.memb[i].size;
+ }
+
+ /* Change total size */
+ dt->size = MAX(1, offset);
+
+ /* Mark the type as packed now */
+ dt->u.compnd.packed=TRUE;
+ } /* end if */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value);
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_is_packed
+ *
+ * Purpose: Checks whether a datatype which is compound (or has compound
+ * components) is packed.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, September 11, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5T_is_packed(H5T_t *dt)
+{
+ htri_t ret_value=TRUE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5T_is_packed,FAIL);
+
+ assert(dt);
+
+ /* Go up the chain as far as possible */
+ while(dt->parent)
+ dt=dt->parent;
+
+ /* If this is a compound datatype, check if it is packed */
+ if(dt->type==H5T_COMPOUND)
+ ret_value=dt->u.compnd.packed;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5T_is_packed() */
+
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 3ccbd0f..80a4075 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -123,8 +123,9 @@ typedef enum H5T_sort_t {
typedef struct H5T_compnd_t {
int nalloc; /*num entries allocated in MEMB array*/
int nmembs; /*number of members defined in struct*/
- H5T_sort_t sorted; /*how are members sorted? */
- struct H5T_cmemb_t *memb; /*array of struct members */
+ H5T_sort_t sorted; /*how are members sorted? */
+ hbool_t packed; /*are members packed together? */
+ struct H5T_cmemb_t *memb; /*array of struct members */
} H5T_compnd_t;
/* An enumeration data type */
@@ -861,4 +862,8 @@ H5_DLL herr_t H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *
/* Array functions */
H5_DLL H5T_t * H5T_array_create(H5T_t *base, int ndims,
const hsize_t dim[/* ndims */], const int perm[/* ndims */]);
+
+/* Compound functions */
+H5_DLL htri_t H5T_is_packed(H5T_t *dt);
+
#endif
diff --git a/test/dtypes.c b/test/dtypes.c
index fe954d8..67f9f84 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -1136,7 +1136,8 @@ test_compound_6(void)
* Function: test_compound_7
*
* Purpose: Tests inserting fields into compound datatypes when the field
- * overlaps the end of the compound datatype.
+ * overlaps the end of the compound datatype. Also, tests
+ * increasing compound type size.
*
* Return: Success: 0
*
@@ -1146,6 +1147,9 @@ test_compound_6(void)
* Tuesday, December 18, 2001
*
* Modifications:
+ * The size of compound datatype can be expanded now.
+ * Raymond Lu
+ * Wednesday, September 10, 2003
*
*-------------------------------------------------------------------------
*/
@@ -1222,6 +1226,35 @@ test_compound_7(void)
goto error;
} /* end if */
+ /* Should not be able to shrink size of compound datatype */
+ H5E_BEGIN_TRY {
+ ret=H5Tset_size(tid2, sizeof(struct s1)/2);
+ } H5E_END_TRY;
+ if(ret>=0) {
+ H5_FAILED();
+ printf("Shrunk compound type?\n");
+ goto error;
+ } /* end if */
+
+ /* Increase compound type size and try inserting field again */
+ if(H5Tset_size(tid2, sizeof(struct s2))<0) {
+ H5_FAILED();
+ printf("Incorrect size for struct 2\n");
+ goto error;
+ } /* end if */
+
+ if( H5Tinsert(tid2,"d",HOFFSET(struct s2,d),H5T_NATIVE_DOUBLE)<0) {
+ H5_FAILED();
+ printf("Can't expand compound datatype\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tget_size(tid2)!=sizeof(struct s2)) {
+ H5_FAILED();
+ printf("Incorrect size for struct 2\n");
+ goto error;
+ } /* end if */
+
/* Release resources */
if (H5Tclose(tid1)<0 || H5Tclose(tid2)<0) {
H5_FAILED();
@@ -1239,6 +1272,153 @@ test_compound_7(void)
/*-------------------------------------------------------------------------
+ * Function: test_compound_8
+ *
+ * Purpose: Tests H5Tpack for compound data types.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, January 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_compound_8(void)
+{
+ typedef struct s1 {
+ char a;
+ int b;
+ } s1;
+
+ typedef struct s2 {
+ char c;
+ s1 d;
+ } s2;
+
+ hid_t tid1, tid2, tid3;
+ herr_t ret;
+
+ TESTING("packing compound data types");
+
+ /* Create first compound datatype */
+ if((tid1 = H5Tcreate( H5T_COMPOUND, sizeof(struct s1)))<0) {
+ H5_FAILED(); AT();
+ printf("Can't create datatype!\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tinsert(tid1,"a",HOFFSET(struct s1,a),H5T_NATIVE_CHAR)<0) {
+ H5_FAILED(); AT();
+ printf("Can't insert field 'a'\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tinsert(tid1,"b",HOFFSET(struct s1,b),H5T_NATIVE_INT)<0) {
+ H5_FAILED(); AT();
+ printf("Can't insert field 'b'\n");
+ goto error;
+ } /* end if */
+
+ /* Test H5Tpack for the first compound type */
+ if(H5Tpack(tid1)<0) {
+ H5_FAILED(); AT();
+ printf("Can't pack the compound data type\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tlock(tid1)<0) {
+ H5_FAILED(); AT();
+ printf("Can't lock the compound data type\n");
+ goto error;
+ } /* end if */
+
+ /* If the type is already packed, packing a locked type is OK */
+ if(H5Tpack(tid1)<0) {
+ H5_FAILED(); AT();
+ printf("Can't pack the compound data type for second time\n");
+ goto error;
+ } /* end if */
+
+
+ /* Create second compound datatype */
+ if((tid2 = H5Tcreate( H5T_COMPOUND, sizeof(struct s2)))<0) {
+ H5_FAILED(); AT();
+ printf("Can't create datatype!\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tinsert(tid2,"c",HOFFSET(struct s2,c),H5T_NATIVE_CHAR)<0) {
+ H5_FAILED(); AT();
+ printf("Can't insert field 'c'\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tinsert(tid2,"d",HOFFSET(struct s2,d),tid1)<0) {
+ H5_FAILED(); AT();
+ printf("Can't insert field 'd'\n");
+ goto error;
+ } /* end if */
+
+ /* Make a copy of the type for later */
+ if((tid3=H5Tcopy(tid2))<0) {
+ H5_FAILED(); AT();
+ printf("Can't copy type #2\n");
+ goto error;
+ } /* end if */
+
+ /* Test H5Tpack for the second compound type */
+ if(H5Tpack(tid2)<0) {
+ H5_FAILED(); AT();
+ printf("Can't pack the compound data type\n");
+ goto error;
+ } /* end if */
+
+ if(H5Tlock(tid2)<0) {
+ H5_FAILED(); AT();
+ printf("Can't lock the compound data type\n");
+ goto error;
+ } /* end if */
+
+ /* If the type is already packed, packing a locked type is OK */
+ if(H5Tpack(tid2)<0) {
+ H5_FAILED(); AT();
+ printf("Can't pack the compound data type for second time\n");
+ goto error;
+ } /* end if */
+
+ /* Lock unpacked type */
+ if(H5Tlock(tid3)<0) {
+ H5_FAILED(); AT();
+ printf("Can't lock the compound data type\n");
+ goto error;
+ } /* end if */
+
+ /* If the type is not packed, packing a locked type shouldn't work */
+ H5E_BEGIN_TRY {
+ ret=H5Tpack(tid3);
+ } H5E_END_TRY;
+ if(ret>=0) {
+ H5_FAILED(); AT();
+ printf("Packing locked datatype worked?\n");
+ goto error;
+ } /* end if */
+
+ /* Can't release resources - they are locked */
+
+ PASSED();
+ return 0;
+
+ error:
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
* Function: test_query
*
* Purpose: Tests query functions of compound and enumeration types.
@@ -4363,6 +4543,7 @@ main(void)
nerrors += test_compound_5();
nerrors += test_compound_6();
nerrors += test_compound_7();
+ nerrors += test_compound_8();
nerrors += test_conv_int ();
nerrors += test_conv_enum_1();
nerrors += test_conv_enum_2();