summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Odtype.c479
-rw-r--r--test/dtypes.c106
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; i<dt->shared->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;