diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-09-12 04:35:48 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-09-12 04:35:48 (GMT) |
commit | 965a4cd7c9a2339bd559a3d5fbbc14a957318da4 (patch) | |
tree | 61df28e4cbb1d88eb1d3390e5a04e1db8cfb4276 /src | |
parent | 987e281c8afa3ebd4113d9efba251be4074fd55f (diff) | |
download | hdf5-965a4cd7c9a2339bd559a3d5fbbc14a957318da4.zip hdf5-965a4cd7c9a2339bd559a3d5fbbc14a957318da4.tar.gz hdf5-965a4cd7c9a2339bd559a3d5fbbc14a957318da4.tar.bz2 |
[svn-r7468] 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
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Odtype.c | 24 | ||||
-rw-r--r-- | src/H5T.c | 10 | ||||
-rw-r--r-- | src/H5Tcompound.c | 178 | ||||
-rw-r--r-- | src/H5Tpkg.h | 6 |
4 files changed, 161 insertions, 57 deletions
diff --git a/src/H5Odtype.c b/src/H5Odtype.c index d6de6f6..2c943cf 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; @@ -2633,7 +2633,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)) + 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"); @@ -3307,6 +3307,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: @@ -3955,10 +3957,12 @@ H5T_set_size(H5T_t *dt, size_t size) case H5T_OPAQUE: /* nothing to check */ break; + case H5T_COMPOUND: - if(size>dt->size) - dt->size = size; + 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 a571d97..e21f865 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -68,7 +68,7 @@ H5T_init_compound_interface(void) * Function: H5Tget_member_offset * * Purpose: Returns the byte offset of the beginning of a member with - * respect to the beginning of the compound data type datum. + * respect to the beginning of the compound datatype datum. * * Return: Success: Byte offset. * @@ -95,7 +95,7 @@ H5Tget_member_offset(hid_t type_id, int membno) /* Check args */ if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound data type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound datatype"); if (membno < 0 || membno >= dt->u.compnd.nmembs) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number"); @@ -112,7 +112,7 @@ done: * * Purpose: Private function for H5Tget_member_offset. Returns the byte * offset of the beginning of a member with respect to the i - * beginning of the compound data type datum. + * beginning of the compound datatype datum. * * Return: Success: Byte offset. * @@ -173,7 +173,7 @@ H5Tget_member_class(hid_t type_id, int membno) /* Check args */ if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound data type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound datatype"); if (membno < 0 || membno >= dt->u.compnd.nmembs) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number"); @@ -188,12 +188,12 @@ done: /*------------------------------------------------------------------------- * Function: H5Tget_member_type * - * Purpose: Returns the data type of the specified member. The caller + * Purpose: Returns the datatype of the specified member. The caller * should invoke H5Tclose() to release resources associated with * the type. * - * Return: Success: An OID of a copy of the member data type; - * modifying the returned data type does not + * Return: Success: An OID of a copy of the member datatype; + * modifying the returned datatype does not * modify the member type. * * Failure: Negative @@ -220,13 +220,13 @@ H5Tget_member_type(hid_t type_id, int membno) /* Check args */ if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype"); if (membno < 0 || membno >= dt->u.compnd.nmembs) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); if ((memb_dt=H5T_get_member_type(dt, membno))==NULL) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to retrieve member type"); if ((ret_value = H5I_register(H5I_DATATYPE, memb_dt)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register data type atom"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register datatype atom"); done: if(ret_value<0) { @@ -244,8 +244,8 @@ done: * Purpose: Private function for H5Tget_member_type. Returns the data * type of the specified member. * - * Return: Success: A copy of the member data type; - * modifying the returned data type does not + * Return: Success: A copy of the member datatype; + * modifying the returned datatype does not * modify the member type. * * Failure: NULL @@ -267,9 +267,9 @@ H5T_get_member_type(H5T_t *dt, int membno) assert(dt); assert(membno >=0 && membno < dt->u.compnd.nmembs); - /* Copy data type into an atom */ + /* Copy datatype into an atom */ if (NULL == (ret_value = H5T_copy(dt->u.compnd.memb[membno].type, H5T_COPY_REOPEN))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member data type"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member datatype"); done: FUNC_LEAVE_NOAPI(ret_value); @@ -279,10 +279,10 @@ done: /*------------------------------------------------------------------------- * Function: H5Tinsert * - * Purpose: Adds another member to the compound data type PARENT_ID. The + * Purpose: Adds another member to the compound datatype PARENT_ID. The * new member has a NAME which must be unique within the - * compound data type. The OFFSET argument defines the start of - * the member in an instance of the compound data type, and + * compound datatype. The OFFSET argument defines the start of + * the member in an instance of the compound datatype, and * MEMBER_ID is the type of the new member. * * Return: Success: Non-negative, the PARENT_ID compound data @@ -303,7 +303,7 @@ done: herr_t H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id) { - H5T_t *parent = NULL; /*the compound parent data type */ + H5T_t *parent = NULL; /*the compound parent datatype */ H5T_t *member = NULL; /*the atomic member type */ herr_t ret_value=SUCCEED; /* Return value */ @@ -314,19 +314,17 @@ H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id) if (parent_id==member_id) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself"); if (NULL == (parent = H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_COMPOUND != parent->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype"); if (H5T_STATE_TRANSIENT!=parent->state) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only"); if (!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name"); if (NULL == (member = H5I_object_verify(member_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); /* Insert */ if (H5T_insert(parent, name, offset, member) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member"); - - parent->packed = FALSE; done: FUNC_LEAVE_API(ret_value); @@ -336,7 +334,7 @@ done: /*------------------------------------------------------------------------- * Function: H5Tpack * - * Purpose: Recursively removes padding from within a compound data type + * Purpose: Recursively removes padding from within a compound datatype * to make it more efficient (space-wise) to store that data. * * Return: Non-negative on success/Negative on failure @@ -358,21 +356,13 @@ 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) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); - /* If datatype has been packed, skip this step and go to done */ - if(dt->packed == TRUE) - HGOTO_DONE(ret_value); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data type is read-only"); + 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 datatype"); /* Pack */ if (H5T_pack(dt) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound data type"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound datatype"); - /* Indicate datatype has been packed */ - dt->packed = TRUE; - done: FUNC_LEAVE_API(ret_value); } @@ -381,7 +371,7 @@ done: /*------------------------------------------------------------------------- * Function: H5T_insert * - * Purpose: Adds a new MEMBER to the compound data type PARENT. The new + * Purpose: Adds a new MEMBER to the compound datatype PARENT. The new * member will have a NAME that is unique within PARENT and an * instance of PARENT will have the member begin at byte offset * OFFSET from the beginning. @@ -454,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 */ @@ -468,7 +481,7 @@ done: /*------------------------------------------------------------------------- * Function: H5T_pack * - * Purpose: Recursively packs a compound data type by removing padding + * Purpose: Recursively packs a compound datatype by removing padding * bytes. This is done in place (that is, destructively). * * Return: Non-negative on success/Negative on failure @@ -487,29 +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) { - /* 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(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"); + + 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 datatype"); + + /* 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 e6127af..2058e6a 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -128,6 +128,7 @@ 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? */ + hbool_t packed; /*are members packed together? */ struct H5T_cmemb_t *memb; /*array of struct members */ } H5T_compnd_t; @@ -194,7 +195,6 @@ struct H5T_t { H5T_class_t type; /*which class of type is this? */ size_t size; /*total size of an instance of this type */ hbool_t force_conv;/* Set if this type always needs to be converted and H5T_conv_noop cannot be called */ - hbool_t packed; /*whether a compound type is packed */ struct H5T_t *parent;/*parent type for derived datatypes */ union { H5T_atomic_t atomic; /* an atomic datatype */ @@ -873,4 +873,8 @@ H5_DLL htri_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); /* 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 |