Skip to content

Commit

Permalink
Disable H5Tset_size for array, vlen and complex number datatypes
Browse files Browse the repository at this point in the history
  • Loading branch information
jhendersonHDF committed Oct 3, 2024
1 parent 9bc0cd8 commit eee1cef
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 76 deletions.
27 changes: 7 additions & 20 deletions src/H5T.c
Original file line number Diff line number Diff line change
Expand Up @@ -2919,7 +2919,9 @@ H5Tset_size(hid_t type_id, size_t size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length");
if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined");
if (H5T_REFERENCE == dt->shared->type)
if (H5T_ARRAY == dt->shared->type || H5T_REFERENCE == dt->shared->type || H5T_COMPLEX == dt->shared->type)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
if (H5T_VLEN == dt->shared->type && H5T_VLEN_STRING != dt->shared->u.vlen.type)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");

/* Modify the datatype */
Expand Down Expand Up @@ -4726,30 +4728,15 @@ H5T__set_size(H5T_t *dt, size_t size)
assert(dt);
assert(dt->shared);
assert(size != 0);
assert(H5T_ARRAY != dt->shared->type);
assert(H5T_REFERENCE != dt->shared->type);
assert(H5T_COMPLEX != dt->shared->type);
assert(H5T_VLEN != dt->shared->type || H5T_VLEN_STRING == dt->shared->u.vlen.type);
assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs));

if (dt->shared->parent) {
size_t new_size = size;

if (dt->shared->type == H5T_COMPLEX) {
if ((new_size % 2) != 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL,
"new datatype size is not evenly divisible by 2");

new_size /= 2;
}

if (H5T__set_size(dt->shared->parent, new_size) < 0)
if (H5T__set_size(dt->shared->parent, size) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type");

/* Adjust size of datatype appropriately */
if (dt->shared->type == H5T_ARRAY)
dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
else if (dt->shared->type == H5T_COMPLEX)
dt->shared->size = 2 * dt->shared->parent->shared->size;
else if (dt->shared->type != H5T_VLEN)
dt->shared->size = dt->shared->parent->shared->size;
}
else {
if (H5T_IS_ATOMIC(dt->shared)) {
Expand Down
32 changes: 10 additions & 22 deletions src/H5Tpublic.h
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ H5_DLLVAR hid_t H5T_VAX_F64_g;
#define H5T_NATIVE_ULLONG (H5OPEN H5T_NATIVE_ULLONG_g)
/**
* \ingroup PDTNAT
* C-style \TText{_Float16} (May be \Code{H5I_INVALID_HID} if platform doesn't support \Code{_Float16} type)
* C-style \TText{_Float16} (May be \TText{H5I_INVALID_HID} if platform doesn't support \TText{_Float16} type)
*/
#define H5T_NATIVE_FLOAT16 (H5OPEN H5T_NATIVE_FLOAT16_g)
/**
Expand All @@ -866,20 +866,20 @@ H5_DLLVAR hid_t H5T_VAX_F64_g;
#define H5T_NATIVE_LDOUBLE (H5OPEN H5T_NATIVE_LDOUBLE_g)
/**
* \ingroup PDTNAT
* C-style \Code{float _Complex} / (MSVC) \Code{_Fcomplex} (May be \Code{H5I_INVALID_HID} if platform doesn't
* support \Code{float _Complex}/\Code{_Fcomplex} type)
* C-style \TText{float _Complex} / (MSVC) \TText{_Fcomplex} (May be \TText{H5I_INVALID_HID} if platform
* doesn't support \TText{float _Complex}/\TText{_Fcomplex} type)
*/
#define H5T_NATIVE_FLOAT_COMPLEX (H5OPEN H5T_NATIVE_FLOAT_COMPLEX_g)
/**
* \ingroup PDTNAT
* C-style \Code{double _Complex} / (MSVC) \Code{_Dcomplex} (May be \Code{H5I_INVALID_HID} if platform doesn't
* support \Code{double _Complex}/\Code{_Dcomplex} type)
* C-style \TText{double _Complex} / (MSVC) \TText{_Dcomplex} (May be \TText{H5I_INVALID_HID} if platform
* doesn't support \TText{double _Complex}/\TText{_Dcomplex} type)
*/
#define H5T_NATIVE_DOUBLE_COMPLEX (H5OPEN H5T_NATIVE_DOUBLE_COMPLEX_g)
/**
* \ingroup PDTNAT
* C-style \Code{long double _Complex} / (MSVC) \Code{_Lcomplex} (May be \Code{H5I_INVALID_HID} if platform
* doesn't support \Code{long double _Complex}/\Code{_Lcomplex} type)
* C-style \TText{long double _Complex} / (MSVC) \TText{_Lcomplex} (May be \TText{H5I_INVALID_HID} if platform
* doesn't support \TText{long double _Complex}/\TText{_Lcomplex} type)
*/
#define H5T_NATIVE_LDOUBLE_COMPLEX (H5OPEN H5T_NATIVE_LDOUBLE_COMPLEX_g)
/**
Expand Down Expand Up @@ -2508,22 +2508,10 @@ H5_DLL hid_t H5Tget_native_type(hid_t type_id, H5T_direction_t direction);
* decrease the size of a compound datatype, but the function will
* fail if the new size is too small to accommodate all member fields.
*
* \li Variable-length datatypes: This function sets the size of
* the base datatype for the variable-length datatype.
*
* \li Array datatypes: This function sets the size of the base
* datatype for the array datatype. The array datatype's size is
* then adjusted to be the size of the base datatype multiplied
* by the number of elements in the array datatype's dimensions.
*
* \li Complex number datatypes: The size set for a complex number
* datatype is the size for the entire datatype, which is shared
* evenly among the datatype's real and imaginary parts. Thus,
* the specified size must be a multiple of 2.
*
* \li Ineligible datatypes: This function cannot be used with
* enumerated datatypes (#H5T_ENUM) or reference datatypes
* (#H5T_REFERENCE).
* enumerated datatypes (#H5T_ENUM), array datatypes (#H5T_ARRAY),
* variable-length array datatypes (#H5T_VLEN), reference datatypes
* (#H5T_REFERENCE), or complex number datatypes (#H5T_COMPLEX).
*
* \see H5Tget_size()
*
Expand Down
162 changes: 128 additions & 34 deletions test/dtypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -6770,7 +6770,6 @@ test_complex_type(void)
const char *driver_name;
char filename[256];
hsize_t dims[1];
herr_t status;
hid_t fid = H5I_INVALID_HID;
hid_t space_id = H5I_INVALID_HID;
hid_t dset_id = H5I_INVALID_HID;
Expand Down Expand Up @@ -6996,60 +6995,29 @@ test_complex_type(void)
}

/*
* Check that H5Tset_size and H5Tset_offset work correctly on a complex
* number type (H5Tset_size sets the size for the whole datatype with
* each of the two parts of the type sharing half the size, while
* H5Tset_offset sets the offset for the base datatype)
* Check that H5Tset_offset works correctly on a complex number type
* (H5Tset_offset sets the offset for the base datatype)
*/
if ((complex_type = H5Tcopy(H5T_NATIVE_FLOAT_COMPLEX)) < 0) {
H5_FAILED();
printf("Can't copy H5T_NATIVE_FLOAT_COMPLEX datatype\n");
goto error;
}

H5E_BEGIN_TRY
{
/* Size must be a multiple of 2 since the real and
* imaginary parts will each share half the datatype size
*/
status = H5Tset_size(complex_type, 13);
}
H5E_END_TRY
if (status >= 0) {
H5_FAILED();
printf("Changed the size of complex number type to a size that isn't a multiple of 2\n");
goto error;
}

if (H5Tset_offset(complex_type, 3) < 0) {
H5_FAILED();
printf("Can't set offset for complex number type's base datatype\n");
goto error;
}
if (H5Tset_size(complex_type, 128) < 0) {
H5_FAILED();
printf("Can't change size of complex number type\n");
goto error;
}

if ((base_type = H5Tget_super(complex_type)) < 0) {
H5_FAILED();
printf("Can't get base datatype of complex number datatype\n");
goto error;
}

type_size = H5Tget_size(base_type);
if (0 == type_size || 64 != type_size) {
H5_FAILED();
printf("Invalid size for complex number type's base datatype\n");
goto error;
}
if (3 != H5Tget_offset(base_type)) {
H5_FAILED();
printf("Invalid offset value for complex number type's base datatype\n");
goto error;
}

if (H5Tclose(base_type) < 0) {
H5_FAILED();
printf("Can't close datatype\n");
Expand Down Expand Up @@ -8821,6 +8789,131 @@ test_array_cmpd_vl(void)
return 1;
} /* end test_array_cmpd_vl() */

/*-------------------------------------------------------------------------
* Function: test_set_size_invalid
*
* Purpose: Tests that H5Tset_size fails when called on an array,
* variable-length, reference or complex number datatype.
*
* Return: Success: 0
* Failure: number of errors
*
*-------------------------------------------------------------------------
*/
static int
test_set_size_invalid(void)
{
hsize_t array_dims[] = {10};
hid_t array_tid = H5I_INVALID_HID;
hid_t vlen_tid = H5I_INVALID_HID;
hid_t ref_tid = H5I_INVALID_HID;
hid_t complex_tid = H5I_INVALID_HID;
hid_t string_tid = H5I_INVALID_HID;
herr_t status;

TESTING("H5Tset_size on ineligible datatypes");

if ((array_tid = H5Tarray_create2(H5T_NATIVE_INT, 1, array_dims)) < 0)
TEST_ERROR;
if ((vlen_tid = H5Tvlen_create(array_tid)) < 0)
TEST_ERROR;
if ((ref_tid = H5Tcopy(H5T_STD_REF)) < 0)
TEST_ERROR;
if ((complex_tid = H5Tcomplex_create(H5T_NATIVE_FLOAT)) < 0)
TEST_ERROR;
if ((string_tid = H5Tcopy(H5T_C_S1)) < 0)
TEST_ERROR;

H5E_BEGIN_TRY
{
status = H5Tset_size(array_tid, 100);
}
H5E_END_TRY;
if (status >= 0) {
H5_FAILED();
AT();
printf("Set size on array datatype\n");
goto error;
}

H5E_BEGIN_TRY
{
status = H5Tset_size(vlen_tid, 100);
}
H5E_END_TRY;
if (status >= 0) {
H5_FAILED();
AT();
printf("Set size on variable-length datatype\n");
goto error;
}

H5E_BEGIN_TRY
{
status = H5Tset_size(ref_tid, 100);
}
H5E_END_TRY;
if (status >= 0) {
H5_FAILED();
AT();
printf("Set size on reference datatype\n");
goto error;
}

H5E_BEGIN_TRY
{
status = H5Tset_size(complex_tid, 100);
}
H5E_END_TRY;
if (status >= 0) {
H5_FAILED();
AT();
printf("Set size on complex number datatype\n");
goto error;
}

/* Should still be able to convert a variable-length string datatype
* back into a fixed-length string datatype even though variable-length
* string datatypes are tested as H5T_VLEN
*/
if (H5Tset_size(string_tid, H5T_VARIABLE) < 0)
TEST_ERROR;
if (H5Tset_size(string_tid, 100) < 0) {
H5_FAILED();
AT();
printf("Unable to set size on variable-length string datatype\n");
goto error;
}

if (H5Tclose(array_tid) < 0)
TEST_ERROR;
if (H5Tclose(vlen_tid) < 0)
TEST_ERROR;
if (H5Tclose(ref_tid) < 0)
TEST_ERROR;
if (H5Tclose(complex_tid) < 0)
TEST_ERROR;
if (H5Tclose(string_tid) < 0)
TEST_ERROR;

PASSED();

return 0;

error:
H5E_BEGIN_TRY
{
H5Tclose(array_tid);
H5Tclose(vlen_tid);
H5Tclose(ref_tid);
H5Tclose(complex_tid);
H5Tclose(string_tid);
}
H5E_END_TRY

return 1;
} /* end test_set_size_invalid() */

/*-------------------------------------------------------------------------
* Function: test_encode
*
Expand Down Expand Up @@ -12785,6 +12878,7 @@ main(void)
nerrors += test_opaque();
nerrors += test_set_order();
nerrors += test_array_cmpd_vl();
nerrors += test_set_size_invalid();

nerrors += test__Float16();
nerrors += test_complex_type();
Expand Down

0 comments on commit eee1cef

Please sign in to comment.