mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-25 17:00:45 +08:00
[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
This commit is contained in:
parent
65d52eaf8e
commit
1c1653aa40
@ -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) {
|
||||
|
80
src/H5T.c
80
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;
|
||||
|
@ -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 */
|
||||
|
@ -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";
|
||||
|
||||
@ -224,6 +226,75 @@ test_vlstrings_basic(void)
|
||||
|
||||
} /* end test_vlstrings_basic() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** 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.
|
||||
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user