From 16fe9dbb8213da1f0abe9ac07f1952bde10c5ca7 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 3 Oct 2006 11:05:09 -0500 Subject: [svn-r12712] Description: Finish 'use the latest version of the format' changes to the datatype object header message. Compound and enumerated types will now be encoded more efficiently by packing the field names & member offsets better. Tested on: Linux 2.6/32 (chicago) Linux 2.6/64 (chicago2) --- src/H5Odtype.c | 479 ++++++++++++++++++++++++++++++++++----------------------- test/dtypes.c | 106 ++++++++++--- 2 files changed, 365 insertions(+), 220 deletions(-) diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 5723808..645f547 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -23,6 +23,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ #include "H5Tpkg.h" /* Datatypes */ +#include "H5Vprivate.h" /* Vectors and arrays */ /* PRIVATE PROTOTYPES */ @@ -79,6 +80,8 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ * objects (floating-point types, currently) (can also also H5T_ARRAY types * also). */ +/* This version also packs compound & enum field names without padding */ +/* This version also encodes the member offset of compound fields more efficiently */ #define H5O_DTYPE_VERSION_3 3 /* The latest version of the format. Look through the 'encode helper' routine @@ -210,124 +213,141 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) break; case H5T_COMPOUND: - /* - * Compound datatypes... - */ - 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 = H5MM_calloc(dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t)); - 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++) { - unsigned ndims = 0; /* Number of dimensions of the array field */ - hsize_t dim[H5O_LAYOUT_NDIMS]; /* Dimensions of the array */ - int perm[H5O_LAYOUT_NDIMS]; /* Dimension permutations */ - unsigned perm_word = 0; /* Dimension permutation information */ - H5T_t *array_dt; /* Temporary pointer to the array datatype */ - H5T_t *temp_type; /* Temporary pointer to the field's datatype */ - - /* Decode the field name */ - dt->shared->u.compnd.memb[i].name = H5MM_xstrdup((const char *)*pp); - /* multiple of 8 w/ null terminator */ - *pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; - - /* Decode the field offset */ - UINT32DECODE(*pp, dt->shared->u.compnd.memb[i].offset); - - /* Older versions of the library allowed a field to have - * intrinsic 'arrayness'. Newer versions of the library - * use the separate array datatypes. */ - if(version == H5O_DTYPE_VERSION_1) { - /* Decode the number of dimensions */ - ndims = *(*pp)++; - HDassert(ndims <= 4); - *pp += 3; /*reserved bytes */ - - /* Decode dimension permutation (unused currently) */ - UINT32DECODE(*pp, perm_word); - - /* Skip reserved bytes */ - *pp += 4; - - /* Decode array dimension sizes */ - for(j = 0; j < 4; j++) - UINT32DECODE(*pp, dim[j]); - } /* end if */ - - /* Allocate space for the field's datatype */ - if(NULL == (temp_type = H5T_alloc())) + { + unsigned offset_nbytes; /* Size needed to encode member offsets */ + + /* Compute the # of bytes required to store a member offset */ + offset_nbytes = (H5V_log2_gen((hsize_t)dt->shared->size) + 7) / 8; + + /* + * Compound datatypes... + */ + 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 = H5MM_calloc(dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t)); + 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++) { + unsigned ndims = 0; /* Number of dimensions of the array field */ + hsize_t dim[H5O_LAYOUT_NDIMS]; /* Dimensions of the array */ + int perm[H5O_LAYOUT_NDIMS]; /* Dimension permutations */ + unsigned perm_word = 0; /* Dimension permutation information */ + H5T_t *array_dt; /* Temporary pointer to the array datatype */ + H5T_t *temp_type; /* Temporary pointer to the field's datatype */ + + /* Decode the field name */ + dt->shared->u.compnd.memb[i].name = H5MM_xstrdup((const char *)*pp); + + /* Version 3 of the datatype message eliminated the padding to multiple of 8 bytes */ + if(version >= H5O_DTYPE_VERSION_3) + /* Advance past name, including null terminator */ + *pp += HDstrlen((const char *)*pp) + 1; + else + /* Advance multiple of 8 w/ null terminator */ + *pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; - /* Decode the field's datatype information */ - if(H5O_dtype_decode_helper(f, pp, temp_type) < 0) { - for(j = 0; j <= i; j++) - H5MM_xfree(dt->shared->u.compnd.memb[j].name); - H5MM_xfree(dt->shared->u.compnd.memb); - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type") - } /* end if */ - - /* Go create the array datatype now, for older versions of the datatype message */ - if(version == H5O_DTYPE_VERSION_1) { - /* Check if this member is an array field */ - if(ndims > 0) { - /* Set up the permutation vector for the array create */ - for(j = 0; j < ndims; j++) - perm[j]=(perm_word >> (j * 8)) & 0xff; - - /* Create the array datatype for the field */ - if((array_dt = H5T_array_create(temp_type, (int)ndims, dim, perm)) == NULL) { - for(j = 0; j <= i; j++) - H5MM_xfree(dt->shared->u.compnd.memb[j].name); - H5MM_xfree(dt->shared->u.compnd.memb); - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create array datatype") - } /* end if */ + /* Decode the field offset */ + /* (starting with version 3 of the datatype message, use the minimum # of bytes required) */ + if(version >= H5O_DTYPE_VERSION_3) + UINT32DECODE_VAR(*pp, dt->shared->u.compnd.memb[i].offset, offset_nbytes) + else + UINT32DECODE(*pp, dt->shared->u.compnd.memb[i].offset) + + /* Older versions of the library allowed a field to have + * intrinsic 'arrayness'. Newer versions of the library + * use the separate array datatypes. */ + if(version == H5O_DTYPE_VERSION_1) { + /* Decode the number of dimensions */ + ndims = *(*pp)++; + HDassert(ndims <= 4); + *pp += 3; /*reserved bytes */ + + /* Decode dimension permutation (unused currently) */ + UINT32DECODE(*pp, perm_word); + + /* Skip reserved bytes */ + *pp += 4; + + /* Decode array dimension sizes */ + for(j = 0; j < 4; j++) + UINT32DECODE(*pp, dim[j]); + } /* end if */ - /* Close the base type for the array */ - H5T_close(temp_type); + /* Allocate space for the field's datatype */ + if(NULL == (temp_type = H5T_alloc())) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Make the array type the type that is set for the field */ - temp_type = array_dt; + /* Decode the field's datatype information */ + if(H5O_dtype_decode_helper(f, pp, temp_type) < 0) { + for(j = 0; j <= i; j++) + H5MM_xfree(dt->shared->u.compnd.memb[j].name); + H5MM_xfree(dt->shared->u.compnd.memb); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type") } /* end if */ - } /* end if */ - /* - * Set the "force conversion" flag if VL datatype fields exist in this - * type or any component types - */ - if(temp_type->shared->force_conv == TRUE) - dt->shared->force_conv = TRUE; - - /* Member size */ - dt->shared->u.compnd.memb[i].size = temp_type->shared->size; - - /* Set the field datatype (finally :-) */ - dt->shared->u.compnd.memb[i].type = temp_type; - - /* 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; + /* Go create the array datatype now, for older versions of the datatype message */ + if(version == H5O_DTYPE_VERSION_1) { + /* Check if this member is an array field */ + if(ndims > 0) { + /* Set up the permutation vector for the array create */ + for(j = 0; j < ndims; j++) + perm[j]=(perm_word >> (j * 8)) & 0xff; + + /* Create the array datatype for the field */ + if((array_dt = H5T_array_create(temp_type, (int)ndims, dim, perm)) == NULL) { + for(j = 0; j <= i; j++) + H5MM_xfree(dt->shared->u.compnd.memb[j].name); + H5MM_xfree(dt->shared->u.compnd.memb); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create array datatype") + } /* end if */ + + /* Close the base type for the array */ + H5T_close(temp_type); + + /* Make the array type the type that is set for the field */ + temp_type = array_dt; } /* 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 */ + + /* + * Set the "force conversion" flag if VL datatype fields exist in this + * type or any component types + */ + if(temp_type->shared->force_conv == TRUE) + dt->shared->force_conv = TRUE; + + /* Member size */ + dt->shared->u.compnd.memb[i].size = temp_type->shared->size; + + /* Set the field datatype (finally :-) */ + dt->shared->u.compnd.memb[i].type = temp_type; + + /* 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 */ + } break; case H5T_ENUM: @@ -343,10 +363,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) NULL == (dt->shared->u.enumer.value = H5MM_calloc(dt->shared->u.enumer.nalloc * dt->shared->parent->shared->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Names, each a multiple of 8 with null termination */ + /* Names */ for(i = 0; i < dt->shared->u.enumer.nmembs; i++) { dt->shared->u.enumer.name[i] = H5MM_xstrdup((const char*)*pp); - *pp += ((HDstrlen((const char*)*pp) + 8) / 8) * 8; + + /* Version 3 of the datatype message eliminated the padding to multiple of 8 bytes */ + if(version >= H5O_DTYPE_VERSION_3) + /* Advance past name, including null terminator */ + *pp += HDstrlen((const char *)*pp) + 1; + else + /* Advance multiple of 8 w/ null terminator */ + *pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; } /* end for */ /* Values */ @@ -516,7 +543,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "byte order is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.lsb_pad) { case H5T_PAD_ZERO: @@ -526,7 +553,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.msb_pad) { case H5T_PAD_ZERO: @@ -536,7 +563,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.u.i.sign) { case H5T_SGN_NONE: @@ -546,7 +573,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "sign scheme is not supported in file format yet") - } + } /* end switch */ UINT16ENCODE(*pp, dt->shared->u.atomic.offset); UINT16ENCODE(*pp, dt->shared->u.atomic.prec); @@ -564,7 +591,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "byte order is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.lsb_pad) { case H5T_PAD_ZERO: @@ -574,7 +601,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.msb_pad) { case H5T_PAD_ZERO: @@ -584,7 +611,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ UINT16ENCODE(*pp, dt->shared->u.atomic.offset); UINT16ENCODE(*pp, dt->shared->u.atomic.prec); @@ -625,7 +652,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "byte order is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.lsb_pad) { case H5T_PAD_ZERO: @@ -635,7 +662,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.msb_pad) { case H5T_PAD_ZERO: @@ -645,7 +672,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.u.f.pad) { case H5T_PAD_ZERO: @@ -655,7 +682,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "bit padding is not supported in file format yet") - } + } /* end switch */ switch (dt->shared->u.atomic.u.f.norm) { case H5T_NORM_NONE: @@ -668,72 +695,90 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "normalization scheme is not supported in file format yet") - } + } /* end switch */ flags |= (dt->shared->u.atomic.u.f.sign << 8) & 0xff00; UINT16ENCODE(*pp, dt->shared->u.atomic.offset); UINT16ENCODE(*pp, dt->shared->u.atomic.prec); - assert (dt->shared->u.atomic.u.f.epos<=255); + HDassert(dt->shared->u.atomic.u.f.epos <= 255); *(*pp)++ = (uint8_t)(dt->shared->u.atomic.u.f.epos); - assert (dt->shared->u.atomic.u.f.esize<=255); + HDassert(dt->shared->u.atomic.u.f.esize <= 255); *(*pp)++ = (uint8_t)(dt->shared->u.atomic.u.f.esize); - assert (dt->shared->u.atomic.u.f.mpos<=255); + HDassert(dt->shared->u.atomic.u.f.mpos <= 255); *(*pp)++ = (uint8_t)(dt->shared->u.atomic.u.f.mpos); - assert (dt->shared->u.atomic.u.f.msize<=255); + HDassert(dt->shared->u.atomic.u.f.msize <= 255); *(*pp)++ = (uint8_t)(dt->shared->u.atomic.u.f.msize); UINT32ENCODE(*pp, dt->shared->u.atomic.u.f.ebias); break; case H5T_COMPOUND: - /* Check for an array datatype somewhere within the compound type */ - if((has_array = H5T_detect_class(dt, H5T_ARRAY)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't detect array class") + { + unsigned offset_nbytes; /* Size needed to encode member offsets */ - /* - * Compound datatypes... - */ - flags = dt->shared->u.compnd.nmembs & 0xffff; - for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { - /* Name, multiple of eight bytes */ - HDstrcpy((char*)(*pp), dt->shared->u.compnd.memb[i].name); - n = HDstrlen(dt->shared->u.compnd.memb[i].name); - for(z = n + 1; z % 8; z++) - (*pp)[z] = '\0'; - *pp += z; - - /* Member offset */ - UINT32ENCODE(*pp, dt->shared->u.compnd.memb[i].offset); - - /* If we don't have any array fields, write out the old style - * member information, for better backward compatibility - * Write out all zeros for the array information, though... + /* Check for an array datatype somewhere within the compound type */ + if((has_array = H5T_detect_class(dt, H5T_ARRAY)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't detect array class") + + /* Compute the # of bytes required to store a member offset */ + offset_nbytes = (H5V_log2_gen((hsize_t)dt->shared->size) + 7) / 8; + + /* + * Compound datatypes... */ - if(!has_array && !use_latest_format) { - unsigned j; + flags = dt->shared->u.compnd.nmembs & 0xffff; + for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { + /* Name */ + HDstrcpy((char*)(*pp), dt->shared->u.compnd.memb[i].name); + + /* Version 3 of the datatype message removed the padding to multiple of 8 bytes */ + n = HDstrlen(dt->shared->u.compnd.memb[i].name); + if(use_latest_format) + *pp += n + 1; + else { + /* Pad name to multiple of 8 bytes */ + for(z = n + 1; z % 8; z++) + (*pp)[z] = '\0'; + *pp += z; + } /* end if */ - /* Dimensionality */ - *(*pp)++ = 0; + /* Member offset */ + /* (starting with version 3 of the datatype message, use the minimum # of bytes required) */ + if(use_latest_format) + UINT32ENCODE_VAR(*pp, dt->shared->u.compnd.memb[i].offset, offset_nbytes) + else + UINT32ENCODE(*pp, dt->shared->u.compnd.memb[i].offset) - /* Reserved */ - *(*pp)++ = 0; - *(*pp)++ = 0; - *(*pp)++ = 0; + /* If we don't have any array fields, write out the old style + * member information, for better backward compatibility + * Write out all zeros for the array information, though... + */ + if(!has_array && !use_latest_format) { + unsigned j; - /* Dimension permutation */ - UINT32ENCODE(*pp, 0); + /* Dimensionality */ + *(*pp)++ = 0; - /* Reserved */ - UINT32ENCODE(*pp, 0); + /* Reserved */ + *(*pp)++ = 0; + *(*pp)++ = 0; + *(*pp)++ = 0; - /* Dimensions */ - for(j = 0; j < 4; j++) + /* Dimension permutation */ UINT32ENCODE(*pp, 0); - } /* end if */ - /* Subtype */ - if(H5O_dtype_encode_helper(f, pp, dt->shared->u.compnd.memb[i].type) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode member type") - } /* end for */ + /* Reserved */ + UINT32ENCODE(*pp, 0); + + /* Dimensions */ + for(j = 0; j < 4; j++) + UINT32ENCODE(*pp, 0); + } /* end if */ + + /* Subtype */ + if(H5O_dtype_encode_helper(f, pp, dt->shared->u.compnd.memb[i].type) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode member type") + } /* end for */ + } break; case H5T_ENUM: @@ -748,11 +793,19 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) /* Names, each a multiple of eight bytes */ for(i=0; ishared->u.enumer.nmembs; i++) { + /* Name */ HDstrcpy((char*)(*pp), dt->shared->u.enumer.name[i]); + + /* Version 3 of the datatype message removed the padding to multiple of 8 bytes */ n = HDstrlen(dt->shared->u.enumer.name[i]); - for(z = n + 1; z % 8; z++) - (*pp)[z] = '\0'; - *pp += z; + if(use_latest_format) + *pp += n + 1; + else { + /* Pad to multiple of 8 bytes */ + for(z = n + 1; z % 8; z++) + (*pp)[z] = '\0'; + *pp += z; + } /* end for */ } /* end for */ /* Values */ @@ -768,11 +821,11 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) /* * Character string types... (not fully implemented) */ - assert (dt->shared->u.atomic.order == H5T_ORDER_NONE); - assert (dt->shared->u.atomic.prec == 8 * dt->shared->size); - assert (dt->shared->u.atomic.offset == 0); - assert (dt->shared->u.atomic.lsb_pad == H5T_PAD_ZERO); - assert (dt->shared->u.atomic.msb_pad == H5T_PAD_ZERO); + HDassert(dt->shared->u.atomic.order == H5T_ORDER_NONE); + HDassert(dt->shared->u.atomic.prec == 8 * dt->shared->size); + HDassert(dt->shared->u.atomic.offset == 0); + HDassert(dt->shared->u.atomic.lsb_pad == H5T_PAD_ZERO); + HDassert(dt->shared->u.atomic.msb_pad == H5T_PAD_ZERO); flags |= (dt->shared->u.atomic.u.s.pad & 0x0f); flags |= (dt->shared->u.atomic.u.s.cset & 0x0f) << 4; @@ -799,13 +852,13 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "byte order is not supported in file format yet") - } + } /* end switch */ UINT16ENCODE(*pp, dt->shared->u.atomic.prec); break; case H5T_ARRAY: /* Array datatypes... */ /* Double-check the number of dimensions */ - assert(dt->shared->u.array.ndims <= H5S_MAX_RANK); + HDassert(dt->shared->u.array.ndims <= H5S_MAX_RANK); /* Encode the number of dimensions */ *(*pp)++ = dt->shared->u.array.ndims; @@ -816,11 +869,11 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) *(*pp)++ = '\0'; /* Encode array dimensions */ - for (i=0; i<(unsigned)dt->shared->u.array.ndims; i++) + for(i = 0; i < (unsigned)dt->shared->u.array.ndims; i++) UINT32ENCODE(*pp, dt->shared->u.array.dim[i]); /* Encode array dimension permutations */ - for (i=0; i<(unsigned)dt->shared->u.array.ndims; i++) + for(i = 0; i < (unsigned)dt->shared->u.array.ndims; i++) UINT32ENCODE(*pp, dt->shared->u.array.perm[i]); /* Encode base type of array's information */ @@ -831,18 +884,19 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) default: /*nothing */ break; - } + } /* end switch */ /* Set version #, based on actual features used for datatype */ - /* (unless the "use the latest format" flag is set) */ - if(use_latest_format) - version = H5O_DTYPE_VERSION_LATEST; - else { - if(has_vax) - version = H5O_DTYPE_VERSION_3; - else - version = (dt->shared->type == H5T_COMPOUND && has_array) ? H5O_DTYPE_VERSION_2 : H5O_DTYPE_VERSION_1; - } /* end else */ + /* (unless the "use the latest format" flag is set, which can "upgrade" the + * format of certain encodings) + */ + if(has_vax || + (use_latest_format && (dt->shared->type == H5T_ENUM || dt->shared->type == H5T_COMPOUND))) + version = H5O_DTYPE_VERSION_3; + else if(has_array) + version = H5O_DTYPE_VERSION_2; + else + version = H5O_DTYPE_VERSION_1; /* Encode the type's class, version and bit field */ *hdr++ = ((unsigned)(dt->shared->type) & 0x0f) | (version << 4); @@ -1050,6 +1104,7 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg) { htri_t has_array; /* Whether a compound datatype has an array inside it */ hbool_t use_latest_format; /* Flag indicating the new group format should be used */ + unsigned offset_nbytes; /* Size needed to encode member offsets */ /* Check for an array datatype somewhere within the compound type */ has_array = H5T_detect_class(dt, H5T_ARRAY); @@ -1058,12 +1113,27 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg) /* Get the file's 'use the latest version of the format' flag */ use_latest_format = H5F_USE_LATEST_FORMAT(f); + /* Compute the # of bytes required to store a member offset */ + offset_nbytes = (H5V_log2_gen((hsize_t)dt->shared->size) + 7) / 8; + /* Compute the total size needed to encode compound datatype */ for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { - ret_value += ((HDstrlen(dt->shared->u.compnd.memb[i].name) + 8) / 8) * 8; + size_t name_len; /* Length of field's name */ + + /* Get length of field's name */ + name_len = HDstrlen(dt->shared->u.compnd.memb[i].name); + + /* Newer versions of the format don't pad out the name */ + if(use_latest_format) + ret_value += name_len + 1; + else + ret_value += ((name_len + 8) / 8) * 8; /* Check for encoding array datatype or using the latest file format */ - if(has_array || use_latest_format) + /* (starting with version 3 of the datatype message, use the minimum # of bytes required) */ + if(use_latest_format) + ret_value += offset_nbytes; /*member offset*/ + else if(has_array) ret_value += 4; /*member offset*/ else ret_value += 4 + /*member offset*/ @@ -1078,10 +1148,27 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg) break; case H5T_ENUM: - ret_value += H5O_dtype_size(f, dt->shared->parent); - for(i = 0; i < dt->shared->u.enumer.nmembs; i++) - ret_value += ((HDstrlen(dt->shared->u.enumer.name[i]) + 8) / 8) * 8; - ret_value += dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size; + { + hbool_t use_latest_format; /* Flag indicating the new group format should be used */ + + /* Get the file's 'use the latest version of the format' flag */ + use_latest_format = H5F_USE_LATEST_FORMAT(f); + + ret_value += H5O_dtype_size(f, dt->shared->parent); + for(i = 0; i < dt->shared->u.enumer.nmembs; i++) { + size_t name_len; /* Length of field's name */ + + /* Get length of field's name */ + name_len = HDstrlen(dt->shared->u.enumer.name[i]); + + /* Newer versions of the format don't pad out the name */ + if(use_latest_format) + ret_value += name_len + 1; + else + ret_value += ((name_len + 8) / 8) * 8; + } /* end for */ + ret_value += dt->shared->u.enumer.nmembs * dt->shared->parent->shared->size; + } break; case H5T_VLEN: diff --git a/test/dtypes.c b/test/dtypes.c index f0d6a35..98c2796 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -4354,7 +4354,7 @@ test_latest(void) double d; }; hid_t file = (-1); /* File ID */ - hid_t tid = (-1); /* Datatype ID */ + hid_t tid1 = (-1), tid2 = (-1); /* Datatype ID */ hid_t fapl = (-1); /* File access property list */ H5G_stat_t sb; /* Stat buffer for committed datatype */ hsize_t old_dtype_oh_size; /* Size of object header with "old" format */ @@ -4364,34 +4364,66 @@ test_latest(void) TESTING("encoding datatypes with the 'use the latest format' flag"); + /* Create a compound datatype */ + if((tid1 = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) + FAIL_STACK_ERROR + if(H5Tinsert(tid1, "a", HOFFSET(struct s1, a), H5T_NATIVE_INT) < 0) + FAIL_STACK_ERROR + if(H5Tinsert(tid1, "b", HOFFSET(struct s1, b), H5T_NATIVE_FLOAT) < 0) + FAIL_STACK_ERROR + if(H5Tinsert(tid1, "c", HOFFSET(struct s1, c), H5T_NATIVE_LONG) < 0) + FAIL_STACK_ERROR + if(H5Tinsert(tid1, "d", HOFFSET(struct s1, d), H5T_NATIVE_DOUBLE) < 0) + FAIL_STACK_ERROR + /* Create file using default FAPL */ h5_fixname(FILENAME[5], H5P_DEFAULT, filename, sizeof filename); if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR - /* Create a compound datatype */ - if((tid = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) + /* Make a copy of the datatype, to commit */ + if((tid2 = H5Tcopy(tid1)) < 0) FAIL_STACK_ERROR - if(H5Tinsert(tid, "a", HOFFSET(struct s1, a), H5T_NATIVE_INT) < 0) + + /* Commit compound datatype */ + if(H5Tcommit(file, compnd_type, tid2) < 0) FAIL_STACK_ERROR - if(H5Tinsert(tid, "b", HOFFSET(struct s1, b), H5T_NATIVE_FLOAT) < 0) + + /* Get information about datatype on disk */ + if(H5Gget_objinfo(file, compnd_type, TRUE, &sb) < 0) FAIL_STACK_ERROR - if(H5Tinsert(tid, "c", HOFFSET(struct s1, c), H5T_NATIVE_LONG) < 0) + old_dtype_oh_size = sb.ohdr.size; + + /* Close datatype */ + if(H5Tclose(tid2) < 0) FAIL_STACK_ERROR - if(H5Tinsert(tid, "d", HOFFSET(struct s1, d), H5T_NATIVE_DOUBLE) < 0) + + /* Close file */ + if(H5Fclose(file) < 0) FAIL_STACK_ERROR - /* Commit compound datatype */ - if(H5Tcommit(file, compnd_type, tid) < 0) + /* Check that datatype has been encoded/decoded correctly */ + if((file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR + + /* Open the dataytpe for query */ + if((tid2 = H5Topen(file, compnd_type)) < 0) + FAIL_STACK_ERROR + + /* Verify that the datatype was encoded/decoded correctly */ + if(H5Tequal(tid1, tid2) <= 0) FAIL_STACK_ERROR /* Get information about datatype on disk */ if(H5Gget_objinfo(file, compnd_type, TRUE, &sb) < 0) FAIL_STACK_ERROR - old_dtype_oh_size = sb.ohdr.size; + + /* Check that the object header info is still the same */ + if(old_dtype_oh_size != sb.ohdr.size) + TEST_ERROR /* Close datatype */ - if(H5Tclose(tid) < 0) + if(H5Tclose(tid2) < 0) FAIL_STACK_ERROR /* Close file */ @@ -4410,20 +4442,12 @@ test_latest(void) if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR - /* Create a compound datatype */ - if((tid = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) - FAIL_STACK_ERROR - if(H5Tinsert(tid, "a", HOFFSET(struct s1, a), H5T_NATIVE_INT) < 0) - FAIL_STACK_ERROR - if(H5Tinsert(tid, "b", HOFFSET(struct s1, b), H5T_NATIVE_FLOAT) < 0) - FAIL_STACK_ERROR - if(H5Tinsert(tid, "c", HOFFSET(struct s1, c), H5T_NATIVE_LONG) < 0) - FAIL_STACK_ERROR - if(H5Tinsert(tid, "d", HOFFSET(struct s1, d), H5T_NATIVE_DOUBLE) < 0) + /* Make a copy of the datatype, to commit */ + if((tid2 = H5Tcopy(tid1)) < 0) FAIL_STACK_ERROR /* Commit compound datatype */ - if(H5Tcommit(file, compnd_type, tid) < 0) + if(H5Tcommit(file, compnd_type, tid2) < 0) FAIL_STACK_ERROR /* Get information about datatype on disk */ @@ -4436,24 +4460,58 @@ test_latest(void) TEST_ERROR /* Close datatype */ - if(H5Tclose(tid) < 0) + if(H5Tclose(tid2) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Check that datatype has been encoded/decoded correctly */ + if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) + FAIL_STACK_ERROR + + /* Open the dataytpe for query */ + if((tid2 = H5Topen(file, compnd_type)) < 0) + FAIL_STACK_ERROR + + /* Verify that the datatype was encoded/decoded correctly */ + if(H5Tequal(tid1, tid2) <= 0) + FAIL_STACK_ERROR + + /* Get information about datatype on disk */ + if(H5Gget_objinfo(file, compnd_type, TRUE, &sb) < 0) + FAIL_STACK_ERROR + + /* Check that the object header info is still the same */ + if(new_dtype_oh_size != sb.ohdr.size) + TEST_ERROR + + /* Close datatype */ + if(H5Tclose(tid2) < 0) FAIL_STACK_ERROR /* Close file */ if(H5Fclose(file) < 0) FAIL_STACK_ERROR + /* Close FAPL */ if(H5Pclose(fapl) < 0) FAIL_STACK_ERROR + /* Close datatype */ + if(H5Tclose(tid1) < 0) + FAIL_STACK_ERROR + PASSED(); return 0; error: H5E_BEGIN_TRY { - H5Tclose(tid); + H5Tclose(tid2); + H5Tclose(tid1); H5Fclose(file); H5Pclose(fapl); } H5E_END_TRY; -- cgit v0.12