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