diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-13 15:19:50 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-13 15:19:50 (GMT) |
commit | e1792ebb22c1fee3eb349b83543e6e915bd1e6f7 (patch) | |
tree | 6e3f936d7809ff0191d17454ba0cb6047abda784 | |
parent | 71f3513337e800f6500551448559cecc6853aca9 (diff) | |
download | hdf5-e1792ebb22c1fee3eb349b83543e6e915bd1e6f7.zip hdf5-e1792ebb22c1fee3eb349b83543e6e915bd1e6f7.tar.gz hdf5-e1792ebb22c1fee3eb349b83543e6e915bd1e6f7.tar.bz2 |
[svn-r7842] Purpose:
Bug fix
Description:
Variable length strings and sequences with NULL pointers were not handled
by library, causing problems access the data. This also affected fill values
for variable-length datatypes.
Solution:
Address the issues in the library by detecting NULL sequences/strings
and avoid trying to convert them.
Patched up dumper to display NULL sequences/strings.
Platforms tested:
FreeBSD 4.9 (sleipnir)
h5committest
-rw-r--r-- | release_docs/RELEASE.txt | 2 | ||||
-rw-r--r-- | src/H5Dio.c | 35 | ||||
-rw-r--r-- | src/H5HG.c | 8 | ||||
-rw-r--r-- | src/H5Ofill.c | 70 | ||||
-rw-r--r-- | src/H5Tconv.c | 152 | ||||
-rw-r--r-- | src/H5Tpkg.h | 19 | ||||
-rw-r--r-- | src/H5Tvlen.c | 402 | ||||
-rw-r--r-- | test/tvlstr.c | 63 | ||||
-rw-r--r-- | test/tvltypes.c | 241 | ||||
-rw-r--r-- | tools/h5dump/h5dump.c | 5 | ||||
-rw-r--r-- | tools/h5dump/h5dumpgentest.c | 71 | ||||
-rwxr-xr-x | tools/h5dump/testh5dump.sh | 1 | ||||
-rwxr-xr-x | tools/h5dump/testh5dumpxml.sh | 2 | ||||
-rw-r--r-- | tools/lib/h5tools_str.c | 102 | ||||
-rw-r--r-- | tools/testfiles/tvldtypes4.h5 | bin | 6208 -> 8192 bytes | |||
-rw-r--r-- | tools/testfiles/tvldtypes4.h5.xml | 55 | ||||
-rw-r--r-- | tools/testfiles/tvldtypes5.ddl | 14 | ||||
-rw-r--r-- | tools/testfiles/tvldtypes5.h5 | bin | 0 -> 8192 bytes | |||
-rw-r--r-- | tools/testfiles/tvldtypes5.h5.xml | 41 | ||||
-rw-r--r-- | tools/testfiles/tvlstr.ddl | 3 | ||||
-rw-r--r-- | tools/testfiles/tvlstr.h5 | bin | 8192 -> 8192 bytes | |||
-rw-r--r-- | tools/testfiles/tvlstr.h5.xml | 4 |
22 files changed, 996 insertions, 294 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 1f5df27..60678c4 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -85,6 +85,8 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Fixed problems with fill values and variable-length types and also + I/O on VL values that were set to NULL. QAK - 2003/11/08 - Fixed problems with MPI datatypes that caused ASCI Q machine to hang. QAK - 2003/10/28 - Removed HDF5_MPI_PREFER_DERIVED_TYPES environment variable support, diff --git a/src/H5Dio.c b/src/H5Dio.c index 8188303..c053737 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -237,25 +237,28 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t if (NULL==(tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Copy the user's data into the buffer for conversion */ + /* Check for actual fill value to replicate */ if(fill==NULL) - HDmemset(tconv_buf,0,src_type_size); - else + /* If there's no fill value, just use zeros */ + HDmemset(tconv_buf,0,dst_type_size); + else { + /* Copy the user's data into the buffer for conversion */ HDmemcpy(tconv_buf,fill,src_type_size); - /* Convert memory buffer into disk buffer */ - /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) { - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") - } else if (!H5T_path_noop(tpath)) { - if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL)))<0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL)))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") - } - - /* Perform data type conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + /* Convert memory buffer into disk buffer */ + /* Set up type conversion function */ + if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) { + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") + } else if (!H5T_path_noop(tpath)) { + if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL)))<0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") + } + + /* Perform data type conversion */ + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed") + } /* end if */ /* Fill the selection in the memory buffer */ if(H5S_select_fill(tconv_buf, dst_type_size, space, buf)<0) @@ -715,9 +715,11 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* assert (idx>0); /* Copy data into the heap */ - HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size); - HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0, - need-(H5HG_SIZEOF_OBJHDR(f)+size)); + if(size>0) { + HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size); + HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0, + need-(H5HG_SIZEOF_OBJHDR(f)+size)); + } /* end if */ heap->cache_info.dirty = TRUE; /* Return value */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index b2595a0..ec34202 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -877,42 +877,44 @@ H5O_fill_convert(void *_fill, H5T_t *dset_type, hid_t dxpl_id) /* * Can we convert between source and destination data types? */ - if (NULL==(tpath=H5T_path_find(fill->type, dset_type, NULL, NULL, dxpl_id))) { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, - "unable to convert between src and dst data types"); - } - if ((src_id = H5I_register(H5I_DATATYPE, - H5T_copy(fill->type, H5T_COPY_TRANSIENT)))<0 || - (dst_id = H5I_register(H5I_DATATYPE, - H5T_copy(dset_type, H5T_COPY_TRANSIENT)))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register data type"); - - /* - * Data type conversions are always done in place, so we need a buffer - * that is large enough for both source and destination. - */ - if (H5T_get_size(fill->type)>=H5T_get_size(dset_type)) { - buf = fill->buf; - } else { - if (NULL==(buf=H5MM_malloc(H5T_get_size(dset_type)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); - HDmemcpy(buf, fill->buf, H5T_get_size(fill->type)); - } - if (H5T_path_bkg(tpath) && NULL==(bkg=H5MM_malloc(H5T_get_size(dset_type)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + if (NULL==(tpath=H5T_path_find(fill->type, dset_type, NULL, NULL, dxpl_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst data types") + + /* Don't bother doing anything if there will be no actual conversion */ + if (!H5T_path_noop(tpath)) { + if ((src_id = H5I_register(H5I_DATATYPE, + H5T_copy(fill->type, H5T_COPY_TRANSIENT)))<0 || + (dst_id = H5I_register(H5I_DATATYPE, + H5T_copy(dset_type, H5T_COPY_TRANSIENT)))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register data type"); + + /* + * Data type conversions are always done in place, so we need a buffer + * that is large enough for both source and destination. + */ + if (H5T_get_size(fill->type)>=H5T_get_size(dset_type)) { + buf = fill->buf; + } else { + if (NULL==(buf=H5MM_malloc(H5T_get_size(dset_type)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + HDmemcpy(buf, fill->buf, H5T_get_size(fill->type)); + } + if (H5T_path_bkg(tpath) && NULL==(bkg=H5MM_malloc(H5T_get_size(dset_type)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); - /* Do the conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, buf, bkg, dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + /* Do the conversion */ + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, buf, bkg, dxpl_id)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); - /* Update the fill message */ - if (buf!=fill->buf) { - H5MM_xfree(fill->buf); - fill->buf = buf; - } - H5T_close(fill->type); - fill->type = NULL; - H5_ASSIGN_OVERFLOW(fill->size,H5T_get_size(dset_type),size_t,ssize_t); + /* Update the fill message */ + if (buf!=fill->buf) { + H5MM_xfree(fill->buf); + fill->buf = buf; + } + H5T_close(fill->type); + fill->type = NULL; + H5_ASSIGN_OVERFLOW(fill->size,H5T_get_size(dset_type),size_t,ssize_t); + } /* end if */ done: if (src_id>=0) diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 897f20b..4950371 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -2384,86 +2384,94 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, s = sp; d = *dptr; - /* Get length of element sequences */ - if((seq_len=(*(src->u.vlen.getlen))(src->u.vlen.f,s))<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length"); - H5_CHECK_OVERFLOW(seq_len,hssize_t,size_t); - src_size=(size_t)seq_len*src_base_size; - dst_size=(size_t)seq_len*dst_base_size; - - /* Check if conversion buffer is large enough, resize if - * necessary */ - if(conv_buf_size<MAX(src_size,dst_size)) { - conv_buf_size=MAX(src_size,dst_size); - if((conv_buf=H5FL_BLK_REALLOC(vlen_seq,conv_buf, conv_buf_size))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); - } /* end if */ - - /* Read in VL sequence */ - if((*(src->u.vlen.read))(src->u.vlen.f,dxpl_id,s,conv_buf,src_size)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data"); - - /* Check if temporary buffer is large enough, resize if necessary */ - /* (Chain off the conversion buffer size) */ - if((tpath->cdata.need_bkg || H5T_detect_class(dst->parent, H5T_VLEN)) - && tmp_buf_size<conv_buf_size) { - /* Set up initial background buffer */ - tmp_buf_size=conv_buf_size; - if((tmp_buf=H5FL_BLK_REALLOC(vlen_seq,tmp_buf,tmp_buf_size))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + /* Check for "nil" source sequence */ + if((*(src->u.vlen.isnull))(src->u.vlen.f,s)) { + /* Write "nil" sequence to destination location */ + if((*(dst->u.vlen.setnull))(dst->u.vlen.f,dxpl_id,d,bg_ptr)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't set VL data to 'nil'"); } /* end if */ + else { + /* Get length of element sequences */ + if((seq_len=(*(src->u.vlen.getlen))(s))<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length"); + H5_CHECK_OVERFLOW(seq_len,hssize_t,size_t); + src_size=(size_t)seq_len*src_base_size; + dst_size=(size_t)seq_len*dst_base_size; + + /* Check if conversion buffer is large enough, resize if + * necessary */ + if(conv_buf_size<MAX(src_size,dst_size)) { + conv_buf_size=MAX(src_size,dst_size); + if((conv_buf=H5FL_BLK_REALLOC(vlen_seq,conv_buf, conv_buf_size))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } /* end if */ - /* If we are writing and there is a nested VL type, read - * the sequence into the background buffer */ - if(nested) { - uint8_t *tmp=bg_ptr; - UINT32DECODE(tmp, bg_seq_len); - if(bg_seq_len>0) { - H5_CHECK_OVERFLOW( bg_seq_len*MAX(src_base_size,dst_base_size) ,hsize_t,size_t); - if(tmp_buf_size<(size_t)(bg_seq_len*MAX(src_base_size, dst_base_size))) { - tmp_buf_size=(size_t)(bg_seq_len*MAX(src_base_size, dst_base_size)); - if((tmp_buf=H5FL_BLK_REALLOC(vlen_seq,tmp_buf, tmp_buf_size))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); - } - H5F_addr_decode(dst->u.vlen.f, (const uint8_t **)&tmp, &(bg_hobjid.addr)); - INT32DECODE(tmp, bg_hobjid.idx); - if(H5HG_read(dst->u.vlen.f,dxpl_id,&bg_hobjid,tmp_buf)==NULL) - HGOTO_ERROR (H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL sequence into background buffer"); - } /* end if */ + /* Read in VL sequence */ + if((*(src->u.vlen.read))(src->u.vlen.f,dxpl_id,s,conv_buf,src_size)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data"); + + /* Check if temporary buffer is large enough, resize if necessary */ + /* (Chain off the conversion buffer size) */ + if((tpath->cdata.need_bkg || H5T_detect_class(dst->parent, H5T_VLEN)) + && tmp_buf_size<conv_buf_size) { + /* Set up initial background buffer */ + tmp_buf_size=conv_buf_size; + if((tmp_buf=H5FL_BLK_REALLOC(vlen_seq,tmp_buf,tmp_buf_size))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } /* end if */ - /* If the sequence gets shorter, pad out the original sequence with zeros */ - H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t); - if((hssize_t)bg_seq_len<seq_len) { - H5_CHECK_OVERFLOW((seq_len-bg_seq_len),hsize_t,size_t); - HDmemset((uint8_t *)tmp_buf+dst_base_size*bg_seq_len,0,(size_t)(seq_len-bg_seq_len)*dst_base_size); + /* If we are writing and there is a nested VL type, read + * the sequence into the background buffer */ + if(nested) { + uint8_t *tmp=bg_ptr; + UINT32DECODE(tmp, bg_seq_len); + if(bg_seq_len>0) { + H5_CHECK_OVERFLOW( bg_seq_len*MAX(src_base_size,dst_base_size) ,hsize_t,size_t); + if(tmp_buf_size<(size_t)(bg_seq_len*MAX(src_base_size, dst_base_size))) { + tmp_buf_size=(size_t)(bg_seq_len*MAX(src_base_size, dst_base_size)); + if((tmp_buf=H5FL_BLK_REALLOC(vlen_seq,tmp_buf, tmp_buf_size))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); + } + H5F_addr_decode(dst->u.vlen.f, (const uint8_t **)&tmp, &(bg_hobjid.addr)); + INT32DECODE(tmp, bg_hobjid.idx); + if(H5HG_read(dst->u.vlen.f,dxpl_id,&bg_hobjid,tmp_buf)==NULL) + HGOTO_ERROR (H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL sequence into background buffer"); + } /* end if */ + + /* If the sequence gets shorter, pad out the original sequence with zeros */ + H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t); + if((hssize_t)bg_seq_len<seq_len) { + H5_CHECK_OVERFLOW((seq_len-bg_seq_len),hsize_t,size_t); + HDmemset((uint8_t *)tmp_buf+dst_base_size*bg_seq_len,0,(size_t)(seq_len-bg_seq_len)*dst_base_size); + } /* end if */ } /* end if */ - } /* end if */ - /* Convert VL sequence */ - H5_CHECK_OVERFLOW(seq_len,hssize_t,hsize_t); - if (H5T_convert(tpath, tsrc_id, tdst_id, (hsize_t)seq_len, 0, bkg_stride, conv_buf, tmp_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed"); + /* Convert VL sequence */ + H5_CHECK_OVERFLOW(seq_len,hssize_t,hsize_t); + if (H5T_convert(tpath, tsrc_id, tdst_id, (hsize_t)seq_len, 0, bkg_stride, conv_buf, tmp_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed"); + + /* Write sequence to destination location */ + if((*(dst->u.vlen.write))(dst->u.vlen.f,dxpl_id,d,conv_buf, bg_ptr, (hsize_t)seq_len,(hsize_t)dst_base_size)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data"); - /* Write sequence to destination location */ - if((*(dst->u.vlen.write))(dst->u.vlen.f,dxpl_id,d,conv_buf, bg_ptr, (hsize_t)seq_len,(hsize_t)dst_base_size)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data"); - - /* For nested VL case, free leftover heap objects from the deeper level if the length of new data elements is shorted than the old data elements.*/ - H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t); - if(nested && seq_len<(hssize_t)bg_seq_len) { - uint8_t *tmp_p=tmp_buf; - tmp_p += seq_len*dst_base_size; - for(i=0; i<(bg_seq_len-seq_len); i++) { - UINT32DECODE(tmp_p, parent_seq_len); - if(parent_seq_len>0) { - H5F_addr_decode(dst->u.vlen.f, (const uint8_t **)&tmp_p, &(parent_hobjid.addr)); - INT32DECODE(tmp_p, parent_hobjid.idx); - if(H5HG_remove(dst->u.vlen.f, dxpl_id,&parent_hobjid)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object"); + /* For nested VL case, free leftover heap objects from the deeper level if the length of new data elements is shorted than the old data elements.*/ + H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t); + if(nested && seq_len<(hssize_t)bg_seq_len) { + uint8_t *tmp_p=tmp_buf; + tmp_p += seq_len*dst_base_size; + for(i=0; i<(bg_seq_len-seq_len); i++) { + UINT32DECODE(tmp_p, parent_seq_len); + if(parent_seq_len>0) { + H5F_addr_decode(dst->u.vlen.f, (const uint8_t **)&tmp_p, &(parent_hobjid.addr)); + INT32DECODE(tmp_p, parent_hobjid.idx); + if(H5HG_remove(dst->u.vlen.f, dxpl_id,&parent_hobjid)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object"); + } } } - } - + } /* end else */ + /* * If we had used a temporary buffer for the destination * then we should copy the value to the true destination diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index dba89bc..01465ef 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -142,9 +142,11 @@ typedef struct H5T_enum_t { } H5T_enum_t; /* VL function pointers */ -typedef hssize_t (*H5T_vlen_getlenfunc_t)(H5F_t *f, void *vl_addr); -typedef herr_t (*H5T_vlen_readfunc_t)(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, size_t len); -typedef herr_t (*H5T_vlen_writefunc_t)(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, void *bg_addr, hsize_t seq_len, hsize_t base_size); +typedef hssize_t (*H5T_vlen_getlenfunc_t)(void *vl_addr); +typedef htri_t (*H5T_vlen_isnullfunc_t)(H5F_t *f, void *vl_addr); +typedef herr_t (*H5T_vlen_readfunc_t)(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, size_t len); +typedef herr_t (*H5T_vlen_writefunc_t)(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, void *_bg, hsize_t seq_len, hsize_t base_size); +typedef herr_t (*H5T_vlen_setnullfunc_t)(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); /* VL types */ typedef enum { @@ -163,8 +165,10 @@ typedef struct H5T_vlen_t { * 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_isnullfunc_t isnull; /* Function to check if VL value is NIL */ H5T_vlen_readfunc_t read; /* Function to read VL sequence into buffer */ H5T_vlen_writefunc_t write; /* Function to write VL sequence from buffer */ + H5T_vlen_setnullfunc_t setnull; /* Function to set a VL value to NIL */ } H5T_vlen_t; /* An opaque datatype */ @@ -859,15 +863,6 @@ H5_DLL htri_t H5T_bit_inc(uint8_t *buf, size_t start, size_t size); /* VL functions */ H5_DLL H5T_t * H5T_vlen_create(const H5T_t *base); -H5_DLL hssize_t H5T_vlen_seq_mem_getlen(H5F_t *f, void *vl_addr); -H5_DLL herr_t H5T_vlen_seq_mem_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, size_t len); -H5_DLL herr_t H5T_vlen_seq_mem_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, void *bg_addr, hsize_t seq_len, hsize_t base_size); -H5_DLL hssize_t H5T_vlen_str_mem_getlen(H5F_t *f, void *vl_addr); -H5_DLL herr_t H5T_vlen_str_mem_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, size_t len); -H5_DLL herr_t H5T_vlen_str_mem_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, void *bg_addr, hsize_t seq_len, hsize_t base_size); -H5_DLL hssize_t H5T_vlen_disk_getlen(H5F_t *f, void *vl_addr); -H5_DLL herr_t H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, size_t len); -H5_DLL herr_t H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, void *bg_addr, hsize_t seq_len, hsize_t base_size); H5_DLL htri_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); /* Array functions */ diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index 1b113a7..13ff95f 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -43,6 +43,21 @@ H5FL_EXTERN(H5T_t); /* Local functions */ static herr_t H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info); +static hssize_t H5T_vlen_seq_mem_getlen(void *_vl); +static htri_t H5T_vlen_seq_mem_isnull(H5F_t *f, void *_vl); +static herr_t H5T_vlen_seq_mem_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); +static herr_t H5T_vlen_seq_mem_write(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); +static herr_t H5T_vlen_seq_mem_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); +static hssize_t H5T_vlen_str_mem_getlen(void *_vl); +static htri_t H5T_vlen_str_mem_isnull(H5F_t *f, void *_vl); +static herr_t H5T_vlen_str_mem_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); +static herr_t H5T_vlen_str_mem_write(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); +static herr_t H5T_vlen_str_mem_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); +static hssize_t H5T_vlen_disk_getlen(void *_vl); +static htri_t H5T_vlen_disk_isnull(H5F_t *f, void *_vl); +static herr_t H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); +static herr_t H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); +static herr_t H5T_vlen_disk_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); /*-------------------------------------------------------------------------- @@ -214,16 +229,20 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Set up the function pointers to access the VL sequence in memory */ dt->u.vlen.getlen=H5T_vlen_seq_mem_getlen; + dt->u.vlen.isnull=H5T_vlen_seq_mem_isnull; dt->u.vlen.read=H5T_vlen_seq_mem_read; dt->u.vlen.write=H5T_vlen_seq_mem_write; + dt->u.vlen.setnull=H5T_vlen_seq_mem_setnull; } else if(dt->u.vlen.type==H5T_VLEN_STRING) { /* size in memory, disk size is different */ dt->size = sizeof(char *); /* Set up the function pointers to access the VL string in memory */ dt->u.vlen.getlen=H5T_vlen_str_mem_getlen; + dt->u.vlen.isnull=H5T_vlen_str_mem_isnull; dt->u.vlen.read=H5T_vlen_str_mem_read; dt->u.vlen.write=H5T_vlen_str_mem_write; + dt->u.vlen.setnull=H5T_vlen_str_mem_setnull; } else { assert(0 && "Invalid VL type"); } @@ -248,8 +267,10 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Set up the function pointers to access the VL information on disk */ /* VL sequences and VL strings are stored identically on disk, so use the same functions */ dt->u.vlen.getlen=H5T_vlen_disk_getlen; + dt->u.vlen.isnull=H5T_vlen_disk_isnull; dt->u.vlen.read=H5T_vlen_disk_read; dt->u.vlen.write=H5T_vlen_disk_write; + dt->u.vlen.setnull=H5T_vlen_disk_setnull; /* Set file ID (since this VL is on disk) */ dt->u.vlen.f=f; @@ -279,27 +300,50 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ -hssize_t -H5T_vlen_seq_mem_getlen(H5F_t UNUSED *f, void *vl_addr) +static hssize_t +H5T_vlen_seq_mem_getlen(void *_vl) { - hvl_t *vl=(hvl_t *)vl_addr; /* Pointer to the user's hvl_t information */ - hssize_t ret_value; /* Return value */ + hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */ - FUNC_ENTER_NOAPI(H5T_vlen_seq_mem_getlen, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_seq_mem_getlen) /* check parameters */ assert(vl); - /* Set return value */ - ret_value=(hssize_t)vl->len; - -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI((hssize_t)vl->len) } /* end H5T_vlen_seq_mem_getlen() */ /*------------------------------------------------------------------------- + * Function: H5T_vlen_seq_mem_isnull + * + * Purpose: Checks if a memory sequence is the "null" sequence + * + * Return: TRUE/FALSE on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static htri_t +H5T_vlen_seq_mem_isnull(H5F_t UNUSED *f, void *_vl) +{ + hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + + FUNC_ENTER_NOINIT(H5T_vlen_seq_mem_isnull) + + /* check parameters */ + assert(vl); + + FUNC_LEAVE_NOAPI((vl->len==0 || vl->p==NULL) ? TRUE : FALSE) +} /* end H5T_vlen_seq_mem_isnull() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_seq_mem_read * * Purpose: "Reads" the memory based VL sequence into a buffer @@ -314,13 +358,12 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -herr_t -H5T_vlen_seq_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *vl_addr, void *buf, size_t len) +static herr_t +H5T_vlen_seq_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void *buf, size_t len) { - hvl_t *vl=(hvl_t *)vl_addr; /* Pointer to the user's hvl_t information */ - herr_t ret_value=SUCCEED; /* Return value */ + hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */ - FUNC_ENTER_NOAPI(H5T_vlen_seq_mem_read, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_seq_mem_read) /* check parameters */ assert(vl && vl->p); @@ -328,8 +371,7 @@ H5T_vlen_seq_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *vl_addr, void HDmemcpy(buf,vl->p,len); -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5T_vlen_seq_mem_read() */ @@ -348,8 +390,8 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -herr_t -H5T_vlen_seq_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, void UNUSED *bg_addr, hsize_t seq_len, hsize_t base_size) +static herr_t +H5T_vlen_seq_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *_vl, void *buf, void UNUSED *_bg, hsize_t seq_len, hsize_t base_size) { H5MM_allocate_t alloc_func; /* Vlen allocation function */ void *alloc_info; /* Vlen allocation information */ @@ -358,10 +400,10 @@ H5T_vlen_seq_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, H5P_genplist_t *plist; /* Property list */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_vlen_seq_mem_write, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_seq_mem_write) /* check parameters */ - assert(vl_addr); + assert(_vl); assert(buf); if(seq_len!=0) { @@ -397,7 +439,7 @@ H5T_vlen_seq_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, H5_ASSIGN_OVERFLOW(vl.len,seq_len,hsize_t,size_t); /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - HDmemcpy(vl_addr,&vl,sizeof(hvl_t)); + HDmemcpy(_vl,&vl,sizeof(hvl_t)); done: FUNC_LEAVE_NOAPI(ret_value) @@ -405,6 +447,42 @@ done: /*------------------------------------------------------------------------- + * Function: H5T_vlen_seq_mem_setnull + * + * Purpose: Sets a VL info object in memory to the "nil" value + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5T_vlen_seq_mem_setnull(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void UNUSED *_bg) +{ + hvl_t vl; /* Temporary hvl_t to use during operation */ + + FUNC_ENTER_NOINIT(H5T_vlen_seq_mem_setnull) + + /* check parameters */ + assert(_vl); + + /* Set the "nil" hvl_t */ + vl.len=0; + vl.p=NULL; + + /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ + HDmemcpy(_vl,&vl,sizeof(hvl_t)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5T_vlen_seq_mem_setnull() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_str_mem_getlen * * Purpose: Retrieves the length of a memory based VL string. @@ -418,27 +496,47 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ -hssize_t -H5T_vlen_str_mem_getlen(H5F_t UNUSED *f, void *vl_addr) +static hssize_t +H5T_vlen_str_mem_getlen(void *_vl) { - char *s=*(char **)vl_addr; /* Pointer to the user's hvl_t information */ - hssize_t ret_value; /* Return value */ + char *s=*(char **)_vl; /* Pointer to the user's string information */ - FUNC_ENTER_NOAPI(H5T_vlen_str_mem_getlen, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_str_mem_getlen) - /* Set return value */ - if(s) - ret_value=(hssize_t)HDstrlen(s); - else - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "null pointer") + /* check parameters */ + assert(s); -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI((hssize_t)HDstrlen(s)) } /* end H5T_vlen_str_mem_getlen() */ /*------------------------------------------------------------------------- + * Function: H5T_vlen_str_mem_isnull + * + * Purpose: Checks if a memory string is a NULL pointer + * + * Return: TRUE/FALSE on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static htri_t +H5T_vlen_str_mem_isnull(H5F_t UNUSED *f, void *_vl) +{ + char *s=*(char **)_vl; /* Pointer to the user's string information */ + + FUNC_ENTER_NOINIT(H5T_vlen_str_mem_isnull) + + FUNC_LEAVE_NOAPI(s==NULL ? TRUE : FALSE); +} /* end H5T_vlen_str_mem_isnull() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_str_mem_read * * Purpose: "Reads" the memory based VL string into a buffer @@ -453,13 +551,12 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -herr_t -H5T_vlen_str_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *vl_addr, void *buf, size_t len) +static herr_t +H5T_vlen_str_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void *buf, size_t len) { - char *s=*(char **)vl_addr; /* Pointer to the user's hvl_t information */ - herr_t ret_value=SUCCEED; /* Return value */ + char *s=*(char **)_vl; /* Pointer to the user's hvl_t information */ - FUNC_ENTER_NOAPI(H5T_vlen_str_mem_read, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_str_mem_read) /* check parameters */ assert(s); @@ -468,8 +565,7 @@ H5T_vlen_str_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *vl_addr, void if(len>0) HDmemcpy(buf,s,len); -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5T_vlen_str_mem_read() */ @@ -488,8 +584,8 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -herr_t -H5T_vlen_str_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, void UNUSED *bg_addr, hsize_t seq_len, hsize_t base_size) +static herr_t +H5T_vlen_str_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *_vl, void *buf, void UNUSED *_bg, hsize_t seq_len, hsize_t base_size) { H5MM_allocate_t alloc_func; /* Vlen allocation function */ void *alloc_info; /* Vlen allocation information */ @@ -498,7 +594,7 @@ H5T_vlen_str_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, H5P_genplist_t *plist; /* Property list */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_vlen_str_mem_write, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_str_mem_write) /* check parameters */ assert(buf); @@ -528,7 +624,7 @@ H5T_vlen_str_mem_write(H5F_t UNUSED *f, hid_t dxpl_id, void *vl_addr, void *buf, t[len]='\0'; /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ - HDmemcpy(vl_addr,&t,sizeof(char *)); + HDmemcpy(_vl,&t,sizeof(char *)); done: FUNC_LEAVE_NOAPI(ret_value) /*lint !e429 The pointer in 't' has been copied */ @@ -536,6 +632,35 @@ done: /*------------------------------------------------------------------------- + * Function: H5T_vlen_str_mem_setnull + * + * Purpose: Sets a VL info object in memory to the "null" value + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5T_vlen_str_mem_setnull(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void UNUSED *_bg) +{ + char *t=NULL; /* Pointer to temporary buffer allocated */ + + FUNC_ENTER_NOINIT(H5T_vlen_str_mem_write) + + /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ + HDmemcpy(_vl,&t,sizeof(char *)); + + FUNC_LEAVE_NOAPI(SUCCEED) /*lint !e429 The pointer in 't' has been copied */ +} /* end H5T_vlen_str_mem_setnull() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_disk_getlen * * Purpose: Retrieves the length of a disk based VL element. @@ -549,26 +674,59 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ -hssize_t -H5T_vlen_disk_getlen(H5F_t UNUSED *f, void *vl_addr) +static hssize_t +H5T_vlen_disk_getlen(void *_vl) { - uint8_t *vl=(uint8_t *)vl_addr; /* Pointer to the disk VL information */ - hssize_t ret_value; /*return value */ + uint8_t *vl=(uint8_t *)_vl; /* Pointer to the disk VL information */ + hssize_t seq_len; /* Sequence length */ - FUNC_ENTER_NOAPI(H5T_vlen_disk_getlen, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_disk_getlen) /* check parameters */ assert(vl); - UINT32DECODE(vl, ret_value); + UINT32DECODE(vl, seq_len); -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(seq_len) } /* end H5T_vlen_disk_getlen() */ /*------------------------------------------------------------------------- + * Function: H5T_vlen_disk_isnull + * + * Purpose: Checks if a disk VL info object is the "nil" object + * + * Return: TRUE/FALSE on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static htri_t +H5T_vlen_disk_isnull(H5F_t *f, void *_vl) +{ + uint8_t *vl=(uint8_t *)_vl; /* Pointer to the disk VL information */ + haddr_t addr; /* Sequence's heap address */ + + FUNC_ENTER_NOINIT(H5T_vlen_disk_isnull) + + /* check parameters */ + assert(vl); + + /* Skip the sequence's length */ + vl+=4; + + /* Get the heap address */ + H5F_addr_decode(f,(const uint8_t **)&vl,&addr); + + FUNC_LEAVE_NOAPI(addr==0 ? TRUE : FALSE) +} /* end H5T_vlen_disk_isnull() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_disk_read * * Purpose: Reads the disk based VL element into a buffer @@ -583,15 +741,15 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -herr_t -H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, size_t UNUSED len) +static herr_t +H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, size_t UNUSED len) { - uint8_t *vl=(uint8_t *)vl_addr; /* Pointer to the user's hvl_t information */ + uint8_t *vl=(uint8_t *)_vl; /* Pointer to the user's hvl_t information */ H5HG_t hobjid; uint32_t seq_len; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_vlen_disk_read, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_disk_read) /* check parameters */ assert(vl); @@ -601,14 +759,14 @@ H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, size_t UNU /* Get the length of the sequence */ UINT32DECODE(vl, seq_len); /* Not used */ - /* Check if this sequence actually has any data */ - if(seq_len!=0) { - /* Get the heap information */ - H5F_addr_decode(f,(const uint8_t **)&vl,&(hobjid.addr)); - INT32DECODE(vl,hobjid.idx); + /* Get the heap information */ + H5F_addr_decode(f,(const uint8_t **)&vl,&(hobjid.addr)); + INT32DECODE(vl,hobjid.idx); + /* Check if this sequence actually has any data */ + if(hobjid.addr>0) { /* Read the VL information from disk */ - if(H5HG_read(f,dxpl_id, &hobjid,buf)==NULL) + if(H5HG_read(f,dxpl_id,&hobjid,buf)==NULL) HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read VL information") } /* end if */ @@ -635,35 +793,37 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, void *bg_addr, hsize_t seq_len, hsize_t base_size) +static herr_t +H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, void *_bg, hsize_t seq_len, hsize_t base_size) { - uint8_t *vl=(uint8_t *)vl_addr; /*Pointer to the user's hvl_t information*/ - uint8_t *bg=(uint8_t *)bg_addr; /*Pointer to the old data hvl_t */ - H5HG_t hobjid; - H5HG_t bg_hobjid; - size_t len; - hsize_t bg_seq_len=0; + uint8_t *vl=(uint8_t *)_vl; /*Pointer to the user's hvl_t information*/ + uint8_t *bg=(uint8_t *)_bg; /*Pointer to the old data hvl_t */ + H5HG_t hobjid; /* New VL sequence's heap ID */ + size_t len; /* Size of new sequence on disk (in bytes) */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_vlen_disk_write, FAIL) + FUNC_ENTER_NOINIT(H5T_vlen_disk_write) /* check parameters */ assert(vl); assert(buf); assert(f); - /* Get the length of the sequence and heap object ID from background data. - * Free heap object for old data. */ + /* Free heap object for old data. */ if(bg!=NULL) { + hsize_t bg_seq_len=0; /* "Background" VL info sequence's length */ + H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */ + + /* Get the length of the sequence and heap object ID from background data. */ HDmemset(&bg_hobjid,0,sizeof(H5HG_t)); UINT32DECODE(bg, bg_seq_len); + /* Get heap information */ + H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr)); + INT32DECODE(bg, bg_hobjid.idx); + /* Free heap object for old data */ - if(bg_seq_len>0) { - /* Get heap information */ - H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr)); - INT32DECODE(bg, bg_hobjid.idx); + if(bg_hobjid.addr>0) { /* Free heap object */ if(H5HG_remove(f, dxpl_id, &bg_hobjid)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") @@ -674,17 +834,12 @@ H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *buf, void *bg_ H5_CHECK_OVERFLOW(seq_len,hsize_t,size_t); UINT32ENCODE(vl, seq_len); - /* Check if this sequence actually has any data */ - if(seq_len!=0) { - /* Write the VL information to disk (allocates space also) */ - H5_ASSIGN_OVERFLOW(len,(seq_len*base_size),hsize_t,size_t); - if(H5HG_insert(f,dxpl_id, len,buf,&hobjid)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write VL information") - } /* end if */ - else - HDmemset(&hobjid,0,sizeof(H5HG_t)); + /* Write the VL information to disk (allocates space also) */ + H5_ASSIGN_OVERFLOW(len,(seq_len*base_size),hsize_t,size_t); + if(H5HG_insert(f,dxpl_id,len,buf,&hobjid)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write VL information") - /* Get the heap information */ + /* Encode the heap information */ H5F_addr_encode(f,&vl,hobjid.addr); INT32ENCODE(vl,hobjid.idx); @@ -693,6 +848,71 @@ done: } /* end H5T_vlen_disk_write() */ +/*------------------------------------------------------------------------- + * Function: H5T_vlen_disk_setnull + * + * Purpose: Sets a VL info object on disk to the "nil" value + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, November 8, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_vlen_disk_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg) +{ + uint8_t *vl=(uint8_t *)_vl; /*Pointer to the user's hvl_t information*/ + uint8_t *bg=(uint8_t *)_bg; /*Pointer to the old data hvl_t */ + uint32_t seq_len=0; /* Sequence length */ + H5HG_t hobjid; /* New VL sequence's heap ID */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5T_vlen_disk_setnull) + + /* check parameters */ + assert(f); + assert(vl); + + /* Free heap object for old data. */ + if(bg!=NULL) { + hsize_t bg_seq_len=0; /* "Background" VL info sequence's length */ + H5HG_t bg_hobjid; /* "Background" VL info sequence's ID info */ + + /* Get the length of the sequence and heap object ID from background data. */ + HDmemset(&bg_hobjid,0,sizeof(H5HG_t)); + UINT32DECODE(bg, bg_seq_len); + + /* Get heap information */ + H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr)); + INT32DECODE(bg, bg_hobjid.idx); + + /* Free heap object for old data */ + if(bg_hobjid.addr>0) { + /* Free heap object */ + if(H5HG_remove(f, dxpl_id, &bg_hobjid)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") + } /* end if */ + } /* end if */ + + /* Set the length of the sequence */ + UINT32ENCODE(vl, seq_len); + + /* Set the "nil" pointer information for the heap ID */ + HDmemset(&hobjid,0,sizeof(H5HG_t)); + + /* Encode the heap information */ + H5F_addr_encode(f,&vl,hobjid.addr); + INT32ENCODE(vl,hobjid.idx); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_vlen_disk_setnull() */ + + /*-------------------------------------------------------------------------- NAME H5T_vlen_reclaim_recurse diff --git a/test/tvlstr.c b/test/tvlstr.c index 8a4ac99..ef35267 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -258,10 +258,12 @@ test_vlstrings_special(void) const char *wdata[SPACE1_DIM1] = {"one", "two", "", "four"}; const char *wdata2[SPACE1_DIM1] = {NULL, NULL, NULL, NULL}; char *rdata[SPACE1_DIM1]; /* Information read in */ + char *fill; /* Fill value */ hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ + hid_t dcpl; /* Dataset creation property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; unsigned i; /* counting variable */ herr_t ret; /* Generic return value */ @@ -288,6 +290,18 @@ test_vlstrings_special(void) dataset=H5Dcreate(fid1,"Dataset3",tid1,sid1,H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); + /* Read from dataset before writing data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i]!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); + } /* end if */ + } /* end for */ + /* Write dataset to disk */ ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); CHECK(ret, FAIL, "H5Dwrite"); @@ -319,14 +333,49 @@ test_vlstrings_special(void) CHECK(ret, FAIL, "H5Dclose"); /* Create another dataset to test nil strings */ - dataset=H5Dcreate(fid1,"Dataset4",tid1,sid1,H5P_DEFAULT); + dcpl=H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl, FAIL, "H5Pcreate"); + + /* Set the fill value for the second dataset */ + fill=NULL; + ret=H5Pset_fill_value(dcpl, tid1, &fill); + CHECK(ret, FAIL, "H5Pset_fill_value"); + + dataset=H5Dcreate(fid1,"Dataset4",tid1,sid1,dcpl); CHECK(dataset, FAIL, "H5Dcreate"); - /* Try to write nil strings to disk. Should fail. */ - H5E_BEGIN_TRY { - H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata2); - } H5E_END_TRY; + /* Close dataset creation property list */ + ret = H5Pclose(dcpl); + CHECK(ret, FAIL, "H5Pclose"); + + /* Read from dataset before writing data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i]!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); + } /* end if */ + } /* end for */ + + /* Try to write nil strings to disk. */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata2); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read nil strings back from disk */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i]!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); + } /* end if */ + } /* end for */ + /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); @@ -432,8 +481,8 @@ static void test_vlstring_type(void) /**************************************************************** ** -** test_vlstrings_special(): Test VL string code for special -** string cases, nil and zero-sized. +** test_compact_vlstring(): Test code for storing VL strings in +** compact datasets. ** ****************************************************************/ static void diff --git a/test/tvltypes.c b/test/tvltypes.c index c924db6..a2f561f 100644 --- a/test/tvltypes.c +++ b/test/tvltypes.c @@ -170,11 +170,14 @@ static void test_vltypes_vlen_atomic(void) { hvl_t wdata[SPACE1_DIM1]; /* Information to write */ + hvl_t wdata2[SPACE1_DIM1]; /* Information to write */ hvl_t rdata[SPACE1_DIM1]; /* Information read in */ + hvl_t fill; /* Fill value */ hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ + hid_t dcpl_pid; /* Dataset creation property list ID */ hid_t xfer_pid; /* Dataset transfer property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; hsize_t size; /* Number of bytes which will be used */ @@ -191,6 +194,9 @@ test_vltypes_vlen_atomic(void) wdata[i].len=i+1; for(j=0; j<(i+1); j++) ((unsigned int *)wdata[i].p)[j]=i*10+j; + + wdata2[i].p=NULL; + wdata2[i].len=0; } /* end for */ /* Create file */ @@ -209,6 +215,34 @@ test_vltypes_vlen_atomic(void) dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); + /* Read from dataset before writing data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i].len!=0 || rdata[i].p!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d].len=%u, rdata[%d].p=%p\n",(int)i,(unsigned)rdata[i].len,(int)i,rdata[i].p); + } /* end if */ + } /* end for */ + + /* Write "nil" data to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata2); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read from dataset with "nil" data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i].len!=0 || rdata[i].p!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d].len=%u, rdata[%d].p=%p\n",(int)i,(unsigned)rdata[i].len,(int)i,rdata[i].p); + } /* end if */ + } /* end for */ + /* Write dataset to disk */ ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); CHECK(ret, FAIL, "H5Dwrite"); @@ -217,6 +251,59 @@ test_vltypes_vlen_atomic(void) ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); + /* Create second dataset, with fill value */ + dcpl_pid=H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl_pid, FAIL, "H5Pcreate"); + + /* Set the fill value for the second dataset */ + fill.p=NULL; fill.len=0; + ret=H5Pset_fill_value(dcpl_pid, tid1, &fill); + CHECK(ret, FAIL, "H5Pset_fill_value"); + + /* Create a second dataset */ + dataset=H5Dcreate(fid1,"Dataset2",tid1,sid1,dcpl_pid); + CHECK(dataset, FAIL, "H5Dcreate"); + + /* Close dataset creation property list */ + ret = H5Pclose(dcpl_pid); + CHECK(ret, FAIL, "H5Pclose"); + + /* Read from dataset before writing data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i].len!=0 || rdata[i].p!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d].len=%u, rdata[%d].p=%p\n",(int)i,(unsigned)rdata[i].len,(int)i,rdata[i].p); + } /* end if */ + } /* end for */ + + /* Write "nil" data to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata2); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read from dataset with "nil" data */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i].len!=0 || rdata[i].p!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d].len=%u, rdata[%d].p=%p\n",(int)i,(unsigned)rdata[i].len,(int)i,rdata[i].p); + } /* end if */ + } /* end for */ + + /* Write data to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + /* Close datatype */ ret = H5Tclose(tid1); CHECK(ret, FAIL, "H5Tclose"); @@ -291,14 +378,88 @@ test_vltypes_vlen_atomic(void) /* Make certain the VL memory has been freed */ VERIFY(mem_used,0,"H5Dvlen_reclaim"); - /* Reclaim the write VL data */ - ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,wdata); + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close datatype */ + ret = H5Tclose(tid1); + CHECK(ret, FAIL, "H5Tclose"); + + /* Close disk dataspace */ + ret = H5Sclose(sid1); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close dataset transfer property list */ + ret = H5Pclose(xfer_pid); + CHECK(ret, FAIL, "H5Pclose"); + + + /* Open second dataset */ + dataset=H5Dopen(fid1,"Dataset2"); + CHECK(dataset, FAIL, "H5Dopen"); + + /* Get dataspace for datasets */ + sid1 = H5Dget_space(dataset); + CHECK(sid1, FAIL, "H5Dget_space"); + + /* Get datatype for dataset */ + tid1 = H5Dget_type(dataset); + CHECK(tid1, FAIL, "H5Dget_type"); + + /* Change to the custom memory allocation routines for reading VL data */ + xfer_pid=H5Pcreate(H5P_DATASET_XFER); + CHECK(xfer_pid, FAIL, "H5Pcreate"); + + ret=H5Pset_vlen_mem_manager(xfer_pid,test_vltypes_alloc_custom,&mem_used,test_vltypes_free_custom,&mem_used); + CHECK(ret, FAIL, "H5Pset_vlen_mem_manager"); + + /* Make certain the correct amount of memory will be used */ + ret=H5Dvlen_get_buf_size(dataset,tid1,sid1,&size); + CHECK(ret, FAIL, "H5Dvlen_get_buf_size"); + + /* 10 elements allocated = 1 + 2 + 3 + 4 elements for each array position */ + VERIFY(size,((SPACE1_DIM1*(SPACE1_DIM1+1))/2)*sizeof(unsigned int),"H5Dvlen_get_buf_size"); + + /* Read dataset from disk */ + ret=H5Dread(dataset,tid1,H5S_ALL,H5S_ALL,xfer_pid,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Make certain the correct amount of memory has been used */ + /* 10 elements allocated = 1 + 2 + 3 + 4 elements for each array position */ + VERIFY(mem_used,((SPACE1_DIM1*(SPACE1_DIM1+1))/2)*sizeof(unsigned int),"H5Dread"); + + /* Compare data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(wdata[i].len!=rdata[i].len) { + num_errs++; + printf("%d: VL data lengths don't match!, wdata[%d].len=%d, rdata[%d].len=%d\n",__LINE__,(int)i,(int)wdata[i].len,(int)i,(int)rdata[i].len); + continue; + } /* end if */ + for(j=0; j<rdata[i].len; j++) { + if( ((unsigned int *)wdata[i].p)[j] != ((unsigned int *)rdata[i].p)[j] ) { + num_errs++; + printf("VL data values don't match!, wdata[%d].p[%d]=%d, rdata[%d].p[%d]=%d\n",(int)i,(int)j, (int)((unsigned int *)wdata[i].p)[j], (int)i,(int)j, (int)((unsigned int *)rdata[i].p)[j]); + continue; + } /* end if */ + } /* end for */ + } /* end for */ + + /* Reclaim the read VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,xfer_pid,rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); + /* Make certain the VL memory has been freed */ + VERIFY(mem_used,0,"H5Dvlen_reclaim"); + /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,wdata); + CHECK(ret, FAIL, "H5Dvlen_reclaim"); + /* Close datatype */ ret = H5Tclose(tid1); CHECK(ret, FAIL, "H5Tclose"); @@ -789,11 +950,13 @@ test_vltypes_compound_vlen_atomic(void) } s1; s1 wdata[SPACE1_DIM1]; /* Information to write */ s1 rdata[SPACE1_DIM1]; /* Information read in */ + s1 fill; /* Fill value */ hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1, tid2; /* Datatype IDs */ hid_t xfer_pid; /* Dataset transfer property list ID */ + hid_t dcpl_pid; /* Dataset creation property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; hsize_t size; /* Number of bytes which will be used */ unsigned i,j; /* counting variables */ @@ -900,14 +1063,84 @@ test_vltypes_compound_vlen_atomic(void) /* Make certain the VL memory has been freed */ VERIFY(mem_used,0,"H5Dvlen_reclaim"); - /* Reclaim the write VL data */ - ret=H5Dvlen_reclaim(tid2,sid1,H5P_DEFAULT,wdata); + /* Close Dataset */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Create a second dataset, with a fill value */ + dcpl_pid=H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl_pid, FAIL, "H5Pcreate"); + + /* Set the fill value for the second dataset */ + HDmemset(&fill,0,sizeof(s1)); + ret=H5Pset_fill_value(dcpl_pid, tid2, &fill); + CHECK(ret, FAIL, "H5Pset_fill_value"); + + dataset=H5Dcreate(fid1,"Dataset2",tid2,sid1,H5P_DEFAULT); + CHECK(dataset, FAIL, "H5Dcreate"); + + /* Close dataset creation property list */ + ret = H5Pclose(dcpl_pid); + CHECK(ret, FAIL, "H5Pclose"); + + /* Read from dataset before writing data */ + ret=H5Dread(dataset,tid2,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Check data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(rdata[i].i!=0 || rdata[i].f!=0.0 || rdata[i].v.len!=0 || rdata[i].v.p!=NULL) { + num_errs++; + printf("VL doesn't match!, rdata[%d].i=%d, rdata[%d].f=%f, rdata[%d].v.len=%u, rdata[%d].v.p=%p\n",(int)i,rdata[i].i,(int)i,rdata[i].f,(int)i,(unsigned)rdata[i].v.len,(int)i,rdata[i].v.p); + } /* end if */ + } /* end for */ + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid2,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + CHECK(ret, FAIL, "H5Dwrite"); + + /* Read dataset from disk */ + ret=H5Dread(dataset,tid2,H5S_ALL,H5S_ALL,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dread"); + + /* Compare data read in */ + for(i=0; i<SPACE1_DIM1; i++) { + if(wdata[i].i!=rdata[i].i) { + num_errs++; + printf("Integer components don't match!, wdata[%d].i=%d, rdata[%d].i=%d\n",(int)i,(int)wdata[i].i,(int)i,(int)rdata[i].i); + continue; + } /* end if */ + if(wdata[i].f!=rdata[i].f) { + num_errs++; + printf("Float components don't match!, wdata[%d].f=%f, rdata[%d].f=%f\n",(int)i,(double)wdata[i].f,(int)i,(double)rdata[i].f); + continue; + } /* end if */ + if(wdata[i].v.len!=rdata[i].v.len) { + num_errs++; + printf("%d: VL data length don't match!, wdata[%d].v.len=%d, rdata[%d].v.len=%d\n",__LINE__,(int)i,(int)wdata[i].v.len,(int)i,(int)rdata[i].v.len); + continue; + } /* end if */ + for(j=0; j<rdata[i].v.len; j++) { + if( ((unsigned int *)wdata[i].v.p)[j] != ((unsigned int *)rdata[i].v.p)[j] ) { + num_errs++; + printf("VL data values don't match!, wdata[%d].v.p[%d]=%d, rdata[%d].v.p[%d]=%d\n",(int)i,(int)j, (int)((unsigned int *)wdata[i].v.p)[j], (int)i,(int)j, (int)((unsigned int *)rdata[i].v.p)[j]); + continue; + } /* end if */ + } /* end for */ + } /* end for */ + + /* Reclaim the VL data */ + ret=H5Dvlen_reclaim(tid2,sid1,H5P_DEFAULT,rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid2,sid1,H5P_DEFAULT,wdata); + CHECK(ret, FAIL, "H5Dvlen_reclaim"); + /* Close datatype */ ret = H5Tclose(tid2); CHECK(ret, FAIL, "H5Tclose"); diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index 77ce159..d79f4ee 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -4846,7 +4846,8 @@ xml_print_strs(hid_t did, int source) for (i = 0; i < ssiz; i++) { if(is_vlstr) { onestring = *(char **)bp; - str_size = (size_t)strlen(onestring); + if(onestring) + str_size = (size_t)strlen(onestring); } else { strncpy(onestring, bp, tsiz); str_size = tsiz; @@ -4854,7 +4855,7 @@ xml_print_strs(hid_t did, int source) indentation(indent + COL); if (!onestring) { - printf("\"%s\"\n", "NULL"); + printf("NULL\n"); } else { char *t_onestring = xml_escape_the_string(onestring, (int)str_size); diff --git a/tools/h5dump/h5dumpgentest.c b/tools/h5dump/h5dumpgentest.c index 0356b2b..901f427 100644 --- a/tools/h5dump/h5dumpgentest.c +++ b/tools/h5dump/h5dumpgentest.c @@ -68,6 +68,7 @@ #define FILE40 "tattr2.h5" #define FILE41 "tcompound_complex.h5" #define FILE42 "tnamed_dtype_attr.h5" +#define FILE43 "tvldtypes5.h5" /* prototypes */ @@ -145,6 +146,10 @@ typedef struct s1_t { #define F42_TYPENAME "Datatype" #define F42_ATTRNAME "Attribute" +/* "File 43" macros */ +/* Name of dataset to create in datafile */ +#define F43_DSETNAME "Dataset" + static void gent_group(void) { hid_t fid, group; @@ -2196,6 +2201,67 @@ static void gent_vldatatypes4(void) assert(ret>=0); } +/* Generate a variable-length dataset with NULL values in it */ +static void gent_vldatatypes5(void) +{ + hvl_t wdata [SPACE1_DIM1]; + hid_t fid1; + hid_t dataset; + hid_t sid1; + hid_t tid1; + hsize_t dims1[] = {SPACE1_DIM1}; + int i,j; /* counting variable */ + herr_t ret; /* Generic return value */ + + /* initialize data for dataset */ + for(i=0; i<SPACE1_DIM1; i++) { + if(i%2) { + wdata[i].len=0; + wdata[i].p=NULL; + } /* end if */ + else { + wdata[i].len=i+5; + wdata[i].p=malloc(sizeof(unsigned)*(i+5)); + for(j=0; j<i+5; j++) + ((unsigned *)wdata[i].p)[j]=j*2; + } /* end else */ + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate (FILE43, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + assert(fid1>0); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple (SPACE1_RANK, dims1, NULL); + assert(sid1>0); + + /* Create a datatype to refer to */ + tid1 = H5Tvlen_create (H5T_NATIVE_UINT); + assert(tid1>0); + + /* Create a dataset */ + dataset = H5Dcreate (fid1, F43_DSETNAME, tid1, sid1, H5P_DEFAULT); + assert(dataset>0); + + ret = H5Dwrite (dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); + assert(ret>=0); + + ret = H5Dclose (dataset); + assert(ret>=0); + + ret = H5Dvlen_reclaim (tid1, sid1, H5P_DEFAULT, wdata); + assert(ret>=0); + + ret = H5Tclose (tid1); + assert(ret>=0); + + ret = H5Sclose (sid1); + assert(ret>=0); + + ret = H5Fclose (fid1); + assert(ret>=0); +} + static void gent_array1(void) { int wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ @@ -2884,8 +2950,8 @@ static void gent_vlstr(void) const char *wdata[SPACE1_DIM1]= { "Four score and seven years ago our forefathers brought forth on this continent a new nation,", "conceived in liberty and dedicated to the proposition that all men are created equal.", - "Now we are engaged in a great civil war,", - "testing whether that nation or any nation so conceived and so dedicated can long endure." + "", + NULL }; /* Information to write */ const char *string_att= "This is the string for the attribute"; hid_t fid1; /* HDF5 File IDs */ @@ -4288,6 +4354,7 @@ int main(void) gent_vldatatypes2(); gent_vldatatypes3(); gent_vldatatypes4(); + gent_vldatatypes5(); gent_array1(); gent_array2(); diff --git a/tools/h5dump/testh5dump.sh b/tools/h5dump/testh5dump.sh index 2e214d8..c0b5165 100755 --- a/tools/h5dump/testh5dump.sh +++ b/tools/h5dump/testh5dump.sh @@ -147,6 +147,7 @@ TOOLTEST tvldtypes1.ddl tvldtypes1.h5 TOOLTEST tvldtypes2.ddl tvldtypes2.h5 TOOLTEST tvldtypes3.ddl tvldtypes3.h5 TOOLTEST tvldtypes4.ddl tvldtypes4.h5 +TOOLTEST tvldtypes5.ddl tvldtypes5.h5 #test for file with variable length string data TOOLTEST tvlstr.ddl tvlstr.h5 diff --git a/tools/h5dump/testh5dumpxml.sh b/tools/h5dump/testh5dumpxml.sh index b7c6f54..d5e3ad5 100755 --- a/tools/h5dump/testh5dumpxml.sh +++ b/tools/h5dump/testh5dumpxml.sh @@ -126,6 +126,8 @@ TOOLTEST tarray7.h5.xml --xml tarray7.h5 TOOLTEST tvldtypes1.h5.xml --xml tvldtypes1.h5 TOOLTEST tvldtypes2.h5.xml --xml tvldtypes2.h5 TOOLTEST tvldtypes3.h5.xml --xml tvldtypes3.h5 +TOOLTEST tvldtypes4.h5.xml --xml tvldtypes4.h5 +TOOLTEST tvldtypes5.h5.xml --xml tvldtypes5.h5 TOOLTEST tvlstr.h5.xml --xml tvlstr.h5 TOOLTEST tsaf.h5.xml --xml tsaf.h5 TOOLTEST tempty.h5.xml --xml tempty.h5 diff --git a/tools/lib/h5tools_str.c b/tools/lib/h5tools_str.c index de1bf72..b3ee8e3 100644 --- a/tools/lib/h5tools_str.c +++ b/tools/lib/h5tools_str.c @@ -510,8 +510,8 @@ char * h5tools_str_sprint(h5tools_str_t *str, const h5dump_t *info, hid_t container, hid_t type, void *vp, h5tools_context_t *ctx) { - size_t n, offset, size, nelmts, start; - char *name, quote = '\0'; + size_t n, offset, size=0, nelmts, start; + char *name; unsigned char *ucp_vp = (unsigned char *)vp; char *cp_vp = (char *)vp; hid_t memb, obj, region; @@ -567,6 +567,7 @@ h5tools_str_sprint(h5tools_str_t *str, const h5dump_t *info, hid_t container, h5tools_print_char(str, info, (unsigned char)(*ucp_vp)); } else if (H5T_STRING == H5Tget_class(type)) { unsigned int i; + char quote = '\0'; char *s; quote = '\0'; @@ -574,64 +575,71 @@ h5tools_str_sprint(h5tools_str_t *str, const h5dump_t *info, hid_t container, /* cp_vp is the pointer into the struct where a `char*' is stored. So we have * to dereference the pointer to get the `char*' to pass to HDstrlen(). */ s = *(char**)cp_vp; - size = HDstrlen(s); + if(s!=NULL) + size = HDstrlen(s); } else { s = cp_vp; size = H5Tget_size(type); } pad = H5Tget_strpad(type); - for (i=0; i<size && (s[i] || pad!=H5T_STR_NULLTERM); i++) { - int j = 1; - - /* - * Count how many times the next character repeats. If the - * threshold is zero then that means it can repeat any number - * of times. - */ - if (info->str_repeat > 0) - while (i + j < size && s[i] == s[i + j]) - j++; - - /* - * Print the opening quote. If the repeat count is high enough to - * warrant printing the number of repeats instead of enumerating - * the characters, then make sure the character to be repeated is - * in it's own quote. - */ - if (info->str_repeat > 0 && j > info->str_repeat) { - if (quote) - h5tools_str_append(str, "%c", quote); - - quote = '\''; - h5tools_str_append(str, "%s%c", i ? " " : "", quote); - } else if (!quote) { - quote = '"'; - h5tools_str_append(str, "%s%c", i ? " " : "", quote); - } + /* Check for NULL pointer for string */ + if(s==NULL) { + h5tools_str_append(str, "NULL"); + } + else { + for (i=0; i<size && (s[i] || pad!=H5T_STR_NULLTERM); i++) { + int j = 1; + + /* + * Count how many times the next character repeats. If the + * threshold is zero then that means it can repeat any number + * of times. + */ + if (info->str_repeat > 0) + while (i + j < size && s[i] == s[i + j]) + j++; - /* Print the character */ - h5tools_print_char(str, info, (unsigned char)(s[i])); - - /* Print the repeat count */ - if (info->str_repeat && j > info->str_repeat) { + /* + * Print the opening quote. If the repeat count is high enough to + * warrant printing the number of repeats instead of enumerating + * the characters, then make sure the character to be repeated is + * in it's own quote. + */ + if (info->str_repeat > 0 && j > info->str_repeat) { + if (quote) + h5tools_str_append(str, "%c", quote); + + quote = '\''; + h5tools_str_append(str, "%s%c", i ? " " : "", quote); + } else if (!quote) { + quote = '"'; + h5tools_str_append(str, "%s%c", i ? " " : "", quote); + } + + /* Print the character */ + h5tools_print_char(str, info, (unsigned char)(s[i])); + + /* Print the repeat count */ + if (info->str_repeat && j > info->str_repeat) { #ifdef REPEAT_VERBOSE - h5tools_str_append(str, "%c repeats %d times", quote, j - 1); + h5tools_str_append(str, "%c repeats %d times", quote, j - 1); #else - h5tools_str_append(str, "%c*%d", quote, j - 1); + h5tools_str_append(str, "%c*%d", quote, j - 1); #endif /* REPEAT_VERBOSE */ - quote = '\0'; - i += j - 1; - } + quote = '\0'; + i += j - 1; + } - } + } - if (quote) - h5tools_str_append(str, "%c", quote); + if (quote) + h5tools_str_append(str, "%c", quote); - if (i == 0) - /*empty string*/ - h5tools_str_append(str, "\"\""); + if (i == 0) + /*empty string*/ + h5tools_str_append(str, "\"\""); + } /* end else */ } else if (H5Tequal(type, H5T_NATIVE_INT)) { memcpy(&tempint, vp, sizeof(int)); h5tools_str_append(str, OPT(info->fmt_int, "%d"), tempint); diff --git a/tools/testfiles/tvldtypes4.h5 b/tools/testfiles/tvldtypes4.h5 Binary files differindex 87aa5f9..ae5f967 100644 --- a/tools/testfiles/tvldtypes4.h5 +++ b/tools/testfiles/tvldtypes4.h5 diff --git a/tools/testfiles/tvldtypes4.h5.xml b/tools/testfiles/tvldtypes4.h5.xml new file mode 100644 index 0000000..6a31194 --- /dev/null +++ b/tools/testfiles/tvldtypes4.h5.xml @@ -0,0 +1,55 @@ +############################# +Expected output for 'h5dump --xml tvldtypes4.h5' +############################# +<?xml version="1.0" encoding="UTF-8"?> +<hdf5:HDF5-File xmlns:hdf5="http://hdf.ncsa.uiuc.edu/DTDs/HDF5-File" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://hdf.ncsa.uiuc.edu/DTDs/HDF5File http://hdf.ncsa.uiuc.edu/DTDs/HDF5-File.xsd"> +<hdf5:RootGroup OBJ-XID="xid_928" H5Path="/"> + <hdf5:Dataset Name="Dataset1" OBJ-XID="xid_976" H5Path= "/Dataset1" Parents="xid_928" H5ParentPaths="/"> + <hdf5:StorageLayout> + <hdf5:ContiguousLayout/> + </hdf5:StorageLayout> + <hdf5:FillValueInfo FillTime="FillOnAlloc" AllocationTime="Late"> + <hdf5:FillValue> + <hdf5:Data> + <!-- VL fill not yet implemented. --> + <hdf5:NoData /> + </hdf5:Data> + </hdf5:FillValue> + </hdf5:FillValueInfo> + <hdf5:Dataspace> + <hdf5:SimpleDataspace Ndims="1"> + <hdf5:Dimension DimSize="4" MaxDimSize="4"/> + </hdf5:SimpleDataspace> + </hdf5:Dataspace> + <hdf5:DataType> + <hdf5:VLType> + <hdf5:DataType> + <hdf5:CompoundType> + <hdf5:Field FieldName="i"> + <hdf5:DataType> + <hdf5:AtomicType> + <hdf5:IntegerType ByteOrder="LE" Sign="true" Size="4" /> + </hdf5:AtomicType> + </hdf5:DataType> + </hdf5:Field> + <hdf5:Field FieldName="f"> + <hdf5:DataType> + <hdf5:AtomicType> + <hdf5:FloatType ByteOrder="LE" Size="4" SignBitLocation="31" ExponentBits="8" ExponentLocation="23" MantissaBits="23" MantissaLocation="0" /> + </hdf5:AtomicType> + </hdf5:DataType> + </hdf5:Field> + </hdf5:CompoundType> + </hdf5:DataType> + </hdf5:VLType> + </hdf5:DataType> +<!-- Note: format of VL data not specified --> + <hdf5:Data> + <hdf5:DataFromFile> + 0 0 10 6.66667 11 7 20 13.3333 21 13.6667 22 14 + 30 20 31 20.3333 32 20.6667 33 21 + </hdf5:DataFromFile> + </hdf5:Data> + </hdf5:Dataset> +</hdf5:RootGroup> +</hdf5:HDF5-File> diff --git a/tools/testfiles/tvldtypes5.ddl b/tools/testfiles/tvldtypes5.ddl new file mode 100644 index 0000000..d199037 --- /dev/null +++ b/tools/testfiles/tvldtypes5.ddl @@ -0,0 +1,14 @@ +############################# +Expected output for 'h5dump tvldtypes5.h5' +############################# +HDF5 "tvldtypes5.h5" { +GROUP "/" { + DATASET "Dataset" { + DATATYPE H5T_VLEN { H5T_STD_U32LE} + DATASPACE SIMPLE { ( 4 ) / ( 4 ) } + DATA { + (0, 2, 4, 6, 8), (), (0, 2, 4, 6, 8, 10, 12), () + } + } +} +} diff --git a/tools/testfiles/tvldtypes5.h5 b/tools/testfiles/tvldtypes5.h5 Binary files differnew file mode 100644 index 0000000..702e45b --- /dev/null +++ b/tools/testfiles/tvldtypes5.h5 diff --git a/tools/testfiles/tvldtypes5.h5.xml b/tools/testfiles/tvldtypes5.h5.xml new file mode 100644 index 0000000..f2452a7 --- /dev/null +++ b/tools/testfiles/tvldtypes5.h5.xml @@ -0,0 +1,41 @@ +############################# +Expected output for 'h5dump --xml tvldtypes5.h5' +############################# +<?xml version="1.0" encoding="UTF-8"?> +<hdf5:HDF5-File xmlns:hdf5="http://hdf.ncsa.uiuc.edu/DTDs/HDF5-File" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://hdf.ncsa.uiuc.edu/DTDs/HDF5File http://hdf.ncsa.uiuc.edu/DTDs/HDF5-File.xsd"> +<hdf5:RootGroup OBJ-XID="xid_928" H5Path="/"> + <hdf5:Dataset Name="Dataset" OBJ-XID="xid_976" H5Path= "/Dataset" Parents="xid_928" H5ParentPaths="/"> + <hdf5:StorageLayout> + <hdf5:ContiguousLayout/> + </hdf5:StorageLayout> + <hdf5:FillValueInfo FillTime="FillOnAlloc" AllocationTime="Late"> + <hdf5:FillValue> + <hdf5:Data> + <!-- VL fill not yet implemented. --> + <hdf5:NoData /> + </hdf5:Data> + </hdf5:FillValue> + </hdf5:FillValueInfo> + <hdf5:Dataspace> + <hdf5:SimpleDataspace Ndims="1"> + <hdf5:Dimension DimSize="4" MaxDimSize="4"/> + </hdf5:SimpleDataspace> + </hdf5:Dataspace> + <hdf5:DataType> + <hdf5:VLType> + <hdf5:DataType> + <hdf5:AtomicType> + <hdf5:IntegerType ByteOrder="LE" Sign="false" Size="4" /> + </hdf5:AtomicType> + </hdf5:DataType> + </hdf5:VLType> + </hdf5:DataType> +<!-- Note: format of VL data not specified --> + <hdf5:Data> + <hdf5:DataFromFile> + 0 2 4 6 8 0 2 4 6 8 10 12 + </hdf5:DataFromFile> + </hdf5:Data> + </hdf5:Dataset> +</hdf5:RootGroup> +</hdf5:HDF5-File> diff --git a/tools/testfiles/tvlstr.ddl b/tools/testfiles/tvlstr.ddl index 2487984..aa19d89 100644 --- a/tools/testfiles/tvlstr.ddl +++ b/tools/testfiles/tvlstr.ddl @@ -21,8 +21,7 @@ GROUP "/" { DATA { "Four score and seven years ago our forefathers brought forth on this continent a new nation,", "conceived in liberty and dedicated to the proposition that all men are created equal.", - "Now we are engaged in a great civil war,", - "testing whether that nation or any nation so conceived and so dedicated can long endure." + "", NULL } } DATATYPE "vl_string_type" H5T_STRING { diff --git a/tools/testfiles/tvlstr.h5 b/tools/testfiles/tvlstr.h5 Binary files differindex f2bf9e4..c00defc 100644 --- a/tools/testfiles/tvlstr.h5 +++ b/tools/testfiles/tvlstr.h5 diff --git a/tools/testfiles/tvlstr.h5.xml b/tools/testfiles/tvlstr.h5.xml index d6f31df..7d9fb5b 100644 --- a/tools/testfiles/tvlstr.h5.xml +++ b/tools/testfiles/tvlstr.h5.xml @@ -48,8 +48,8 @@ Expected output for 'h5dump --xml tvlstr.h5' <hdf5:DataFromFile> "Four score and seven years ago our forefathers brought forth on this continent a new nation," "conceived in liberty and dedicated to the proposition that all men are created equal." - "Now we are engaged in a great civil war," - "testing whether that nation or any nation so conceived and so dedicated can long endure." + "" + NULL </hdf5:DataFromFile> </hdf5:Data> </hdf5:Dataset> |