From e1792ebb22c1fee3eb349b83543e6e915bd1e6f7 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 13 Nov 2003 10:19:50 -0500 Subject: [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 --- release_docs/RELEASE.txt | 2 + src/H5Dio.c | 35 ++-- src/H5HG.c | 8 +- src/H5Ofill.c | 70 +++---- src/H5Tconv.c | 152 +++++++------- src/H5Tpkg.h | 19 +- src/H5Tvlen.c | 402 +++++++++++++++++++++++++++++--------- test/tvlstr.c | 63 +++++- test/tvltypes.c | 241 ++++++++++++++++++++++- tools/h5dump/h5dump.c | 5 +- tools/h5dump/h5dumpgentest.c | 71 ++++++- tools/h5dump/testh5dump.sh | 1 + tools/h5dump/testh5dumpxml.sh | 2 + tools/lib/h5tools_str.c | 102 +++++----- tools/testfiles/tvldtypes4.h5 | Bin 6208 -> 8192 bytes tools/testfiles/tvldtypes4.h5.xml | 55 ++++++ tools/testfiles/tvldtypes5.ddl | 14 ++ tools/testfiles/tvldtypes5.h5 | Bin 0 -> 8192 bytes tools/testfiles/tvldtypes5.h5.xml | 41 ++++ tools/testfiles/tvlstr.ddl | 3 +- tools/testfiles/tvlstr.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tvlstr.h5.xml | 4 +- 22 files changed, 996 insertions(+), 294 deletions(-) create mode 100644 tools/testfiles/tvldtypes4.h5.xml create mode 100644 tools/testfiles/tvldtypes5.ddl create mode 100644 tools/testfiles/tvldtypes5.h5 create mode 100644 tools/testfiles/tvldtypes5.h5.xml 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) diff --git a/src/H5HG.c b/src/H5HG.c index 47df258..67fb7c1 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -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_sizeu.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_sizeu.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_size0) { - 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_size0) { + 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_lenu.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=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; i0); + + /* 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; istr_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; istr_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 index 87aa5f9..ae5f967 100644 Binary files a/tools/testfiles/tvldtypes4.h5 and b/tools/testfiles/tvldtypes4.h5 differ 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' +############################# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 new file mode 100644 index 0000000..702e45b Binary files /dev/null and b/tools/testfiles/tvldtypes5.h5 differ 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' +############################# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 2 4 6 8 0 2 4 6 8 10 12 + + + + + 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 index f2bf9e4..c00defc 100644 Binary files a/tools/testfiles/tvlstr.h5 and b/tools/testfiles/tvlstr.h5 differ 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' "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 -- cgit v0.12