From 1c1653aa40acb537d91f37013e5de7ee83e8e052 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Fri, 29 Mar 2002 18:46:56 -0500 Subject: [svn-r5123] Purpose: Bug fix(#697) Description: Variable-length string wasn't treated as string. Solution: Added character set and padding into VL string type. Platforms tested: FreeBSD --- src/H5Odtype.c | 8 ++++++ src/H5T.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/H5Tpkg.h | 3 +++ test/tvlstr.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 150 insertions(+), 16 deletions(-) diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 545531f..ed94cd4 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -352,6 +352,10 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) case H5T_VLEN: /* Variable length datatypes... */ /* Set the type of VL information, either sequence or string */ dt->u.vlen.type = (H5T_vlen_type_t)(flags & 0x0f); + if(dt->u.vlen.type == H5T_VLEN_STRING) { + dt->u.vlen.pad = (H5T_str_t)((flags>>4) & 0x0f); + dt->u.vlen.cset = (H5T_cset_t)((flags>>8) & 0x0f); + } /* end if */ /* Decode base type of VL information */ if (NULL==(dt->parent = H5FL_ALLOC(H5T_t,1))) @@ -730,6 +734,10 @@ H5O_dtype_encode_helper(uint8_t **pp, const H5T_t *dt) case H5T_VLEN: /* Variable length datatypes... */ flags |= (dt->u.vlen.type & 0x0f); + if(dt->u.vlen.type == H5T_VLEN_STRING) { + flags |= (dt->u.vlen.pad & 0x0f) << 4; + flags |= (dt->u.vlen.cset & 0x0f) << 8; + } /* end if */ /* Encode base type of VL information */ if (H5O_dtype_encode_helper(pp, dt->parent)<0) { diff --git a/src/H5T.c b/src/H5T.c index d86aff0..50d67e4 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -3755,14 +3755,23 @@ H5Tget_cset(hid_t type_id) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_CSET_ERROR, "not a data type"); } - if (dt->parent) dt = dt->parent; /*defer to parent*/ - if (H5T_STRING != dt->type) { + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == + dt->u.vlen.type))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_CSET_ERROR, "operation not defined for data type class"); } /* result */ - cset = dt->u.atomic.u.s.cset; + if(H5T_STRING == dt->type) + cset = dt->u.atomic.u.s.cset; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + cset = dt->u.vlen.cset; + else + HRETURN_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_CSET_ERROR, + "can't get cset info"); FUNC_LEAVE(cset); } @@ -3806,14 +3815,24 @@ H5Tset_cset(hid_t type_id, H5T_cset_t cset) HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal character set type"); } - if (dt->parent) dt = dt->parent; /*defer to parent*/ - if (H5T_STRING != dt->type) { + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == + dt->u.vlen.type))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); } /* Commit */ - dt->u.atomic.u.s.cset = cset; + if(H5T_STRING == dt->type) + dt->u.atomic.u.s.cset = cset; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + dt->u.vlen.cset = cset; + else + HRETURN_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, + "can't set cset info"); + FUNC_LEAVE(SUCCEED); } @@ -3853,14 +3872,23 @@ H5Tget_strpad(hid_t type_id) NULL == (dt = H5I_object(type_id))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_STR_ERROR, "not a data type"); } - if (dt->parent) dt = dt->parent; /*defer to parent*/ - if (H5T_STRING != dt->type) { + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == + dt->u.vlen.type))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_STR_ERROR, "operation not defined for data type class"); } /* result */ - strpad = dt->u.atomic.u.s.pad; + if(H5T_STRING == dt->type) + strpad = dt->u.atomic.u.s.pad; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + strpad = dt->u.vlen.pad; + else + HRETURN_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, + "can't get strpad info"); FUNC_LEAVE(strpad); } @@ -3914,14 +3942,24 @@ H5Tset_strpad(hid_t type_id, H5T_str_t strpad) if (strpad < 0 || strpad >= H5T_NSTR) { HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal string pad type"); } - if (dt->parent) dt = dt->parent; /*defer to parent*/ - if (H5T_STRING != dt->type) { + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == + dt->u.vlen.type))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); } /* Commit */ - dt->u.atomic.u.s.pad = strpad; + if(H5T_STRING == dt->type) + dt->u.atomic.u.s.pad = strpad; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + dt->u.vlen.pad = strpad; + else + HRETURN_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, + "can't set strpad info"); + FUNC_LEAVE(SUCCEED); } @@ -6043,6 +6081,8 @@ H5T_set_size(H5T_t *dt, size_t size) /* Convert string to variable-length datatype */ if(size==H5T_VARIABLE) { H5T_t *base = NULL; /* base data type */ + H5T_cset_t tmp_cset; /* Temp. cset info */ + H5T_str_t tmp_strpad; /* Temp. strpad info */ /* Get a copy of unsigned char type as the base/parent type */ if (NULL==(base=H5I_object(H5T_NATIVE_UCHAR))) @@ -6053,17 +6093,27 @@ H5T_set_size(H5T_t *dt, size_t size) dt->type = H5T_VLEN; /* - * Force conversions (i.e. memory to memory conversions should duplicate - * data, not point to the same VL strings) + * Force conversions (i.e. memory to memory conversions + * should duplicate data, not point to the same VL strings) */ dt->force_conv = TRUE; + /* Before we mess with the info in the union, extract the + * values we need */ + tmp_cset=dt->u.atomic.u.s.cset; + tmp_strpad=dt->u.atomic.u.s.pad; + /* This is a string, not a sequence */ dt->u.vlen.type = H5T_VLEN_STRING; + /* Set character set and padding information */ + dt->u.vlen.cset = tmp_cset; + dt->u.vlen.pad = tmp_strpad; + /* Set up VL information */ if (H5T_vlen_mark(dt, NULL, H5T_VLEN_MEMORY)<0) - HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location"); + HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "invalid VL location"); } else { prec = 8 * size; diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 1ffaa4f..9be4778 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -98,6 +98,9 @@ typedef herr_t (*H5T_vlen_writefunc_t)(hid_t dxpl_id, H5F_t *f, void *vl_addr, v typedef struct H5T_vlen_t { H5T_vlen_type_t type; /* Type of VL data in buffer */ H5T_vlen_loc_t loc; /* Location of VL data in buffer */ + H5T_cset_t cset; /* For VL string. character set */ + H5T_str_t pad; /* For VL string. space or null padding of + * extra bytes */ H5F_t *f; /* File ID (if VL data is on disk) */ H5T_vlen_getlenfunc_t getlen; /* Function to get VL sequence size (in element units, not bytes) */ H5T_vlen_readfunc_t read; /* Function to read VL sequence into buffer */ diff --git a/test/tvlstr.c b/test/tvlstr.c index e17b0c8..3c09746 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -41,6 +41,8 @@ #define SPACE2_DIM1 10 #define SPACE2_DIM2 10 +#define VLSTR_TYPE "vl_string_type" + /* String for testing attributes */ static const char *string_att = "This is the string for the attribute"; @@ -226,6 +228,75 @@ test_vlstrings_basic(void) /**************************************************************** ** +** test_vlstring_type(): Test VL string type. +** Tests if VL string is treated as string. +** +****************************************************************/ +static void test_vlstring_type(void) +{ + hid_t fid; /* HDF5 File IDs */ + hid_t tid_vlstr, str; + H5T_cset_t cset; + H5T_str_t pad; + size_t size; + herr_t ret; + + /* Output message about test being performed */ + MESSAGE(5, ("Testing VL String type\n")); + + /* Create file */ + fid = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a datatype to refer to */ + tid_vlstr = H5Tcopy(H5T_C_S1); + CHECK(tid_vlstr, FAIL, "H5Tcopy"); + + /* Change padding and verify it */ + ret = H5Tset_strpad(tid_vlstr, H5T_STR_NULLPAD); + CHECK(ret, FAIL, "H5Tset_strpad"); + pad = H5Tget_strpad(tid_vlstr); + VERIFY(pad, H5T_STR_NULLPAD, "H5Tget_strpad"); + + /* Convert to variable-length string */ + ret = H5Tset_size(tid_vlstr, H5T_VARIABLE); + CHECK(ret, FAIL, "H5Tset_size"); + + /* Check default character set and padding */ + cset = H5Tget_cset(tid_vlstr); + VERIFY(cset, H5T_CSET_ASCII, "H5Tget_cset"); + pad = H5Tget_strpad(tid_vlstr); + VERIFY(pad, H5T_STR_NULLPAD, "H5Tget_strpad"); + + /* Commit variable-length string datatype to storage */ + ret = H5Tcommit(fid, VLSTR_TYPE, tid_vlstr); + CHECK(ret, FAIL, "H5Tcommit"); + + /* Close datatype */ + ret = H5Tclose(tid_vlstr); + CHECK(ret, FAIL, "H5Tclose"); + + + /* Open the variable-length string datatype just created */ + tid_vlstr = H5Topen(fid, VLSTR_TYPE); + CHECK(tid_vlstr, FAIL, "H5Topen"); + + /* Verify character set and padding */ + cset = H5Tget_cset(tid_vlstr); + VERIFY(cset, H5T_CSET_ASCII, "H5Tget_cset"); + pad = H5Tget_strpad(tid_vlstr); + VERIFY(pad, H5T_STR_NULLPAD, "H5Tget_strpad"); + + /* Close datatype and file */ + ret = H5Tclose(tid_vlstr); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + +} /* end test_vlstring_type() */ + +/**************************************************************** +** ** test_write_vl_string_attribute(): Test basic VL string code. ** Tests writing VL strings as attributes ** @@ -353,7 +424,9 @@ test_vlstrings(void) MESSAGE(5, ("Testing Variable-Length Strings\n")); /* These next tests use the same file */ - test_vlstrings_basic(); /* Test basic VL string datatype */ + /* Test basic VL string datatype */ + test_vlstrings_basic(); + test_vlstring_type(); /* Test using VL strings in attributes */ test_write_vl_string_attribute(); -- cgit v0.12