From 898ba82d42aa46cbca59fca31f47d5bce3e8dd72 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 13 Nov 2003 10:20:23 -0500 Subject: [svn-r7844] 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 | 34 ++-- src/H5HG.c | 8 +- src/H5Ofill.c | 63 +++---- src/H5Tconv.c | 150 ++++++++-------- src/H5Tpkg.h | 19 +- src/H5Tvlen.c | 410 ++++++++++++++++++++++++++++++++---------- 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 | 101 ++++++----- tools/testfiles/tvldtypes4.h5 | Bin 6208 -> 8192 bytes tools/testfiles/tvlstr.ddl | 3 +- tools/testfiles/tvlstr.h5 | Bin 8192 -> 8192 bytes tools/testfiles/tvlstr.h5.xml | 12 +- 18 files changed, 885 insertions(+), 300 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index decb346..1ac85b6 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -60,6 +60,8 @@ Bug Fixes since HDF5-1.6.1 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 1821205..c4d0087 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -237,25 +237,27 @@ 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 + 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 4d0e52d..f463b1c 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -743,9 +743,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 bb3f613..a2ffdb1 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -879,38 +879,41 @@ H5O_fill_convert(void *_fill, H5T_t *dset_type, hid_t 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"); + /* 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 5a66ef2..b880d2e 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -2353,85 +2353,93 @@ 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 diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 80a4075..4bbd46d 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -138,9 +138,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); /* A VL datatype */ typedef struct H5T_vlen_t { @@ -151,8 +153,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 data type */ @@ -849,15 +853,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(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); /* Array functions */ H5_DLL H5T_t * H5T_array_create(H5T_t *base, int ndims, diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index 274d122..f6e1086 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -41,6 +41,21 @@ H5FL_EXTERN(H5T_t); /* Local functions */ static htri_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_loc_t loc); static herr_t H5T_vlen_reclaim_recurse(void *elem, 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); /*-------------------------------------------------------------------------- @@ -212,16 +227,20 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_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"); } @@ -246,8 +265,10 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_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; @@ -277,26 +298,49 @@ done: * *------------------------------------------------------------------------- */ -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: + * + *------------------------------------------------------------------------- + */ +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 @@ -310,13 +354,12 @@ done: * *------------------------------------------------------------------------- */ -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); @@ -324,8 +367,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() */ @@ -343,8 +385,8 @@ done: * *------------------------------------------------------------------------- */ -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 */ @@ -353,10 +395,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) { @@ -392,7 +434,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); @@ -400,6 +442,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. @@ -413,30 +491,46 @@ done: * *------------------------------------------------------------------------- */ -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) /* check parameters */ - if (!s) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "null pointer"); - - /* Set return value */ - if(s) - ret_value=(hssize_t)HDstrlen(s); - else - ret_value = 0; + 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: + * + *------------------------------------------------------------------------- + */ +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 @@ -450,25 +544,21 @@ done: * *------------------------------------------------------------------------- */ -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); assert(buf); - if(s && buf && len>0) + if(len>0) HDmemcpy(buf,s,len); - if(!s && len==(size_t)-1) - buf = NULL; -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5T_vlen_str_mem_read() */ @@ -486,8 +576,8 @@ done: * *------------------------------------------------------------------------- */ -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 */ @@ -496,7 +586,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); @@ -526,7 +616,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); @@ -534,6 +624,34 @@ 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: + * + *------------------------------------------------------------------------- + */ +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. @@ -547,25 +665,59 @@ done: * *------------------------------------------------------------------------- */ -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 @@ -579,15 +731,15 @@ done: * *------------------------------------------------------------------------- */ -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); @@ -597,19 +749,19 @@ 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) - HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read VL information"); + if(H5HG_read(f,dxpl_id,&hobjid,buf)==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read VL information") } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_vlen_disk_read() */ @@ -631,38 +783,40 @@ 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"); + HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object") } /* end if */ } /* end if */ @@ -670,25 +824,85 @@ 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); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* 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 5a4e902..78e2f03 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 45e2027..e38e8fd 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; @@ -566,6 +566,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'; @@ -573,64 +574,70 @@ 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); - } + 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/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 d74cd1f..7d9fb5b 100644 --- a/tools/testfiles/tvlstr.h5.xml +++ b/tools/testfiles/tvlstr.h5.xml @@ -3,26 +3,26 @@ Expected output for 'h5dump --xml tvlstr.h5' ############################# - + - + "This is the string for the attribute" - + - + @@ -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