From 416a86e3ce3b967553003267a6e77c037e21815f Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 22 Feb 2001 16:53:30 -0500 Subject: [svn-r3488] Purpose: Code Movement Description: Moved tools code into their own special subdirectories. Platforms tested: Linux, Kelgia --- tools/h4toh5/Dependencies | 0 tools/h4toh5/Makefile.in | 60 + tools/h4toh5/h4toh5anno.c | 665 ++++++ tools/h4toh5/h4toh5image.c | 861 ++++++++ tools/h4toh5/h4toh5main.c | 1629 +++++++++++++++ tools/h4toh5/h4toh5main.h | 109 + tools/h4toh5/h4toh5pal.c | 202 ++ tools/h4toh5/h4toh5sds.c | 1096 ++++++++++ tools/h4toh5/h4toh5test.c | 3944 ++++++++++++++++++++++++++++++++++++ tools/h4toh5/h4toh5util.c | 1633 +++++++++++++++ tools/h4toh5/h4toh5util.h | 232 +++ tools/h4toh5/h4toh5vdata.c | 831 ++++++++ tools/h4toh5/h4toh5vgroup.c | 812 ++++++++ tools/h4toh5/testh4toh5.sh | 249 +++ tools/h5dump/Dependencies | 0 tools/h5dump/Makefile.in | 65 + tools/h5dump/h5dump.c | 4680 +++++++++++++++++++++++++++++++++++++++++++ tools/h5dump/h5dump.h | 22 + tools/h5dump/h5dumptst.c | 2577 ++++++++++++++++++++++++ tools/h5dump/testh5dump.sh | 197 ++ 20 files changed, 19864 insertions(+) create mode 100644 tools/h4toh5/Dependencies create mode 100644 tools/h4toh5/Makefile.in create mode 100644 tools/h4toh5/h4toh5anno.c create mode 100644 tools/h4toh5/h4toh5image.c create mode 100644 tools/h4toh5/h4toh5main.c create mode 100644 tools/h4toh5/h4toh5main.h create mode 100644 tools/h4toh5/h4toh5pal.c create mode 100644 tools/h4toh5/h4toh5sds.c create mode 100644 tools/h4toh5/h4toh5test.c create mode 100644 tools/h4toh5/h4toh5util.c create mode 100644 tools/h4toh5/h4toh5util.h create mode 100644 tools/h4toh5/h4toh5vdata.c create mode 100644 tools/h4toh5/h4toh5vgroup.c create mode 100755 tools/h4toh5/testh4toh5.sh create mode 100644 tools/h5dump/Dependencies create mode 100644 tools/h5dump/Makefile.in create mode 100644 tools/h5dump/h5dump.c create mode 100644 tools/h5dump/h5dump.h create mode 100644 tools/h5dump/h5dumptst.c create mode 100755 tools/h5dump/testh5dump.sh diff --git a/tools/h4toh5/Dependencies b/tools/h4toh5/Dependencies new file mode 100644 index 0000000..e69de29 diff --git a/tools/h4toh5/Makefile.in b/tools/h4toh5/Makefile.in new file mode 100644 index 0000000..71019e2 --- /dev/null +++ b/tools/h4toh5/Makefile.in @@ -0,0 +1,60 @@ +## HDF5 Library Makefile(.in) +## +## Copyright (C) 2001 National Center for Supercomputing Applications. +## All rights reserved. +## +## +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +SUBDIRS= +@COMMENCE@ + +## Add include directory to the C preprocessor flags, add -lh5tools and +## -lhdf5 to the list of libraries. +## +CPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src \ + -I$(top_srcdir)/tools/lib @CPPFLAGS@ + +## Test programs and scripts. +## +TEST_PROGS= +TEST_SCRIPTS=@TESTH4TOH5@ + +## These are our main targets: library and tools. +## +LIBTOOLS=../lib/libh5tools.la +LIBHDF5=$(top_builddir)/src/libhdf5.la + +PUB_PROGS=@H4TOH5@ +PROGS=$(PUB_PROGS) $(TEST_PROGS) @H4TOH5TEST@ + +## Source and object files for h4toh5 converter. +## +PROG_SRC=h4toh5main.c h4toh5vgroup.c h4toh5vdata.c h4toh5sds.c \ + h4toh5image.c h4toh5pal.c h4toh5anno.c h4toh5util.c +PROG_OBJ=$(PROG_SRC:.c=.lo) + +PRIVATE_HDR=h4toh5main.h h4toh5util.h + +## Source and object files for the tests +## +TEST_SRC=h4toh5test.c +TEST_OBJ=$(TEST_SRC:.c=.lo) + +## Programs have to be built before they can be tested! +## +check test _test: $(PROGS) + +## How to build the programs... They all depend on the hdf5 library and +## the tools library compiled in this directory. +## +$(PROGS): $(LIBTOOLS) $(LIBHDF5) + +h4toh5test: h4toh5test.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ h4toh5test.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +h4toh5: $(PROG_OBJ) + @$(LT_LINK_EXE) $(CFLAGS) -o $@ $(PROG_OBJ) $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +@CONCLUDE@ diff --git a/tools/h4toh5/h4toh5anno.c b/tools/h4toh5/h4toh5anno.c new file mode 100644 index 0000000..cd09e26 --- /dev/null +++ b/tools/h4toh5/h4toh5anno.c @@ -0,0 +1,665 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +converting an hdf4 annotation into an hdf5 attribute of the corresponding object. + + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + +#include "h4toh5main.h" + + +/*------------------------------------------------------------------------- + * Function: Annofil_h4_to_h5 + * + * Purpose: translate file annotation object into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: file identifier + h5_group: hdf5 group id + + *------------------------------------------------------------------------- + */ + +int Annofil_h4_to_h5(int32 file_id,hid_t h5group){ + + int32 an_id; + int32 ann_id; + int32 i; + + int32 ann_length; + + int32 n_file_label = 0; + int32 n_file_desc = 0; + int32 n_data_label = 0; + int32 n_data_desc = 0; + + int32 istat; + + char* ann_buf; + char anno_labelname[30]; + char anno_descname[30]; + char index_str[5]; + + hid_t h5_sid; + hid_t h5_aid; + hid_t sh5str_type; + hid_t sh5str1_type; + hid_t ret; + + an_id = ANstart(file_id); + + if(an_id < 0) { + printf("error in obtaining an_id. \n"); + return FAIL; + } + + istat = ANfileinfo(an_id,&n_file_label,&n_file_desc, + &n_data_label,&n_data_desc); + + if(istat == FAIL) { + printf("error getting file information.\n"); + ANend(file_id); + return FAIL; + } + + for (i = 0; i < n_file_label; i++) { + + ann_id = ANselect(an_id,i,AN_FILE_LABEL); + if(ann_id == FAIL) { + printf("error in obtaining annotation id. \n"); + ANend(file_id); + return FAIL; + } + + ann_length = ANannlen(ann_id); + if(ann_length == FAIL) { + printf("error in obtaining annotation length. \n"); + ANend(file_id); + ANendaccess(ann_id); + return FAIL; + } + + ann_buf = malloc((size_t)ann_length + 1); + if(ann_buf == NULL) { + printf("error in allocating memory. \n"); + return FAIL; + } + h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(char)); + istat = ANreadann(ann_id,ann_buf,ann_length+1); + + if(istat==FAIL) { + printf("fail to read file information. \n"); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + h5_sid = H5Screate(H5S_SCALAR); + + if (h5_sid < 0) { + printf("failed to create attribute space for"); + printf(" HDF4 FILE ANNOTATION. \n"); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + if ((sh5str_type = mkstr(ann_length+1,H5T_STR_SPACEPAD))<0) { + printf("error in making string at FILE lABEL ANNO. \n"); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + if(conv_int_str(i,index_str)== FAIL) { + printf("fail to convert integer into character format.\n"); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + strcpy(anno_labelname,HDF4_FILE_LABEL); + strcat(anno_labelname,"_"); + strcat(anno_labelname,index_str); + + + h5_aid = H5Acreate(h5group,anno_labelname,sh5str_type, + h5_sid,H5P_DEFAULT); + + if (h5_aid <0) { + printf("failed to obtain attribute id for"); + printf(" File annotation. \n"); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + ret = H5Awrite(h5_aid,sh5str_type,(void *)ann_buf); + + if (ret <0) { + printf("failed to obtain attribute.\n "); + ANend(file_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + ret = H5Sclose(h5_sid); + ret = H5Aclose(h5_aid); + free(ann_buf); + ANendaccess(ann_id); + + } + + for (i = 0; i < n_file_desc; i++) { + + ann_id = ANselect(an_id,i,AN_FILE_DESC); + if(ann_id == FAIL) { + printf("error in obtaining annotation id. \n"); + ANend(an_id); + return FAIL; + } + + ann_length = ANannlen(ann_id); + + if(ann_length == FAIL) { + printf("error in obtaining annotation length. \n"); + ANend(an_id); + ANendaccess(ann_id); + return FAIL; + } + + ann_buf = malloc((size_t)ann_length+1); + if(ann_buf == NULL) { + printf("error in allocating memory. \n"); + ANend(an_id); + ANendaccess(ann_id); + return FAIL; + } + h4toh5_ZeroMemory(ann_buf,ann_length+1); + + istat = ANreadann(ann_id,ann_buf,ann_length+1); + + if(istat == FAIL) { + printf("error reading file information. \n"); + ANend(an_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + if ((sh5str1_type = mkstr(ann_length+1,H5T_STR_SPACEPAD))<0) { + printf("error in making string at FILE DESC. \n"); + ANend(an_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + if(conv_int_str(i,index_str)==FAIL) { + printf("fail to convert integer into character format.\n"); + ANend(an_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + strcpy(anno_descname,HDF4_FILE_DESC); + strcat(anno_descname,"_"); + strcat(anno_descname,index_str); + + h5_sid = H5Screate(H5S_SCALAR); + + if (h5_sid < 0) { + printf("failed to create attribute space for"); + printf(" HDF4 FILE ANNOTATION. \n"); + ANend(an_id); + ANendaccess(ann_id); + free(ann_buf); + return FAIL; + } + + h5_aid = H5Acreate(h5group,anno_descname,sh5str1_type, + h5_sid,H5P_DEFAULT); + + if (h5_aid <0) { + + printf("failed to obtain attribute id for"); + printf(" File annotation. \n"); + ANend(an_id); + ANendaccess(ann_id); + H5Sclose(h5_sid); + free(ann_buf); + return FAIL; + } + + ret = H5Awrite(h5_aid,sh5str1_type,(void *)ann_buf); + + if (ret <0) { + printf("failed to obtain attribute.\n "); + ANend(an_id); + ANendaccess(ann_id); + H5Sclose(h5_sid); + H5Aclose(h5_aid); + free(ann_buf); + return FAIL; + } + + ret = H5Sclose(h5_sid); + ret = H5Aclose(h5_aid); + free(ann_buf); + ANendaccess(ann_id); + } + ANend(an_id); + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: Annoobj_h4_to_h5 + * + * Purpose: translate annotation object into attribute of hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: file identifier + obj_ref: object reference + obj_tag: object tag + h5group: hdf5 group + + *------------------------------------------------------------------------- + */ +int Annoobj_h4_to_h5(int32 file_id,int32 obj_ref, int32 obj_tag, + hid_t h5group){ + + int32 an_id; + int32 ann_id; + int32 i; + int32 status; + int32 ann_length; + + int32 n_file_label =-1; + int32 n_file_desc =-1; + int32 n_data_label =-1; + int32 n_data_desc =-1; + + int num_lab_anno; + int num_des_anno; + int32 istat; + int32* des_anno_list=NULL; + int32* lab_anno_list=NULL; + + char* ann_buf; + char* ann_obj_name; + char ann_labelname[30]; + + char index_str[5]; + + hid_t h5_sid; + hid_t h5_aid; + hid_t sh5str_type; + hid_t ret; + + an_id = ANstart(file_id); + if(an_id == FAIL) { + printf("fail to start annotation interface.\n"); + return FAIL; + } + + istat = ANfileinfo(an_id,&n_file_label,&n_file_desc, + &n_data_label,&n_data_desc); + + if(istat == FAIL ) { + printf("error getting file information.\n"); + ANend(an_id); + return FAIL; + } + + num_lab_anno = ANnumann(an_id,AN_DATA_LABEL,obj_tag,obj_ref); + num_des_anno = ANnumann(an_id,AN_DATA_DESC,obj_tag,obj_ref); + + if (num_lab_anno == FAIL) { + printf("error getting number of annotation data label.\n"); + ANend(an_id); + return FAIL; + } + + if (num_des_anno == FAIL) { + printf("error getting number of annotation object label.\n"); + ANend(an_id); + return FAIL; + } + + if(num_lab_anno > 0) { + + for(i=0; i 0) { + + + for (i = 0; i< num_des_anno;i++) { + + ann_id = ANselect(an_id,i,AN_DATA_DESC); + if(ann_id == FAIL) { + printf("error in obtaining annotation id.\n"); + ANend(an_id); + return FAIL; + } + ann_length = ANannlen(ann_id); + if(ann_length == FAIL) { + printf("error in getting annotation length. \n"); + ANendaccess(ann_id); + ANend(an_id); + return FAIL; + } + + ann_buf = malloc((size_t)ann_length+1); + + if(ann_buf == NULL) { + printf("error in allocating annotation memory.\n"); + ANendaccess(ann_id); + ANend(an_id); + return FAIL; + } + + h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(char)); + ANreadann(ann_id,ann_buf,ann_length+1); + + if ((sh5str_type = mkstr(ann_length+1,H5T_STR_SPACEPAD))<0) { + printf("error in making string at OBJECT DESC. \n"); + ANend(an_id); + free(des_anno_list); + free(ann_buf); + return FAIL; + } + + if(conv_int_str(i,index_str)== FAIL) { + printf("fail to convert annotation index into character format.\n"); + ANend(an_id); + free(ann_buf); + free(des_anno_list); + return FAIL; + } + ann_obj_name = trans_tag_name(obj_tag,AN_DATA_DESC); + if(ann_obj_name == NULL) { + printf("error in obtaining tag name. \n"); + ANend(an_id); + free(ann_buf); + free(des_anno_list); + return FAIL; + } + + strcpy(ann_labelname,ann_obj_name); + strcat(ann_labelname,"_"); + strcat(ann_labelname,index_str); + + h5_sid = H5Screate(H5S_SCALAR); + + if (h5_sid < 0) { + printf("failed to create attribute space for"); + printf(" HDF4 OBJECT ANNOTATION. \n"); + ANend(an_id); + free(des_anno_list); + free(ann_buf); + free(ann_obj_name); + return FAIL; + } + + h5_aid = H5Acreate(h5group,ann_labelname,sh5str_type, + h5_sid,H5P_DEFAULT); + + if (h5_aid <0) { + + ANend(an_id); + free(ann_buf); + free(des_anno_list); + free(ann_obj_name); + printf("failed to obtain attribute id for "); + printf("File annotation. \n"); + return FAIL; + } + + ret = H5Awrite(h5_aid,sh5str_type,(void *)ann_buf); + + if (ret <0) { + printf("failed to obtain attribute.\n "); + ANend(an_id); + free(ann_buf); + free(des_anno_list); + free(ann_obj_name); + return FAIL; + } + ret = H5Sclose(h5_sid); + ret = H5Aclose(h5_aid); + free(ann_obj_name); + + free(ann_buf); + } + + } + ANend(an_id); + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: trans_tag_name + * + * Purpose: in annotation routine, + translate annotation object tag into corresponding HDF5 object + name. + + * + * Return: NULL if failed, HDF5 object name if successful. + * + * In : + obj_tag: hdf4 object tag + annot_type: hdf4 annotation type + + *------------------------------------------------------------------------- + */ +char* trans_tag_name(int32 obj_tag,ann_type annot_type){ + + char* obj_name; + + obj_name = malloc(strlen(HDF4_VGROUP_LABEL)+1); + + if(obj_name == NULL) { + printf("error in obtaining tag name. \n"); + return NULL; + } + + if (obj_tag == DFTAG_NDG || obj_tag == DFTAG_SDG || obj_tag == DFTAG_SD) { + + if(annot_type == AN_DATA_LABEL) + strcpy(obj_name,HDF4_SDS_LABEL); + + else if(annot_type == AN_DATA_DESC) + strcpy(obj_name,HDF4_SDS_DESC); + else + return NULL; + } + + else if(obj_tag == DFTAG_RIG || obj_tag == DFTAG_RI || obj_tag == DFTAG_RI8) + { + if(annot_type == AN_DATA_LABEL) + strcpy(obj_name,HDF4_IMAGE_LABEL); + else if(annot_type == AN_DATA_DESC) + strcpy(obj_name,HDF4_IMAGE_DESC); + else + return NULL; + } + + else if(obj_tag == DFTAG_VG) { + if(annot_type == AN_DATA_LABEL) + strcpy(obj_name,HDF4_VGROUP_LABEL); + else if(annot_type == AN_DATA_DESC) + strcpy(obj_name,HDF4_VGROUP_DESC); + else + return NULL; + } + + else if(obj_tag == DFTAG_VS || obj_tag == DFTAG_VH) { + if(annot_type == AN_DATA_LABEL) + strcpy(obj_name,HDF4_VDATA_LABEL); + else if(annot_type == AN_DATA_DESC) + strcpy(obj_name,HDF4_VDATA_DESC); + else + return NULL; + } + + else if(obj_tag == DFTAG_LUT) { + if(annot_type == AN_DATA_LABEL) + strcpy(obj_name,HDF4_PAL_LABEL); + else if(annot_type == AN_DATA_DESC) + strcpy(obj_name,HDF4_PAL_DESC); + else + return NULL; + } + return obj_name; +} + + + + + + + + + + + diff --git a/tools/h4toh5/h4toh5image.c b/tools/h4toh5/h4toh5image.c new file mode 100644 index 0000000..8fbbdc0 --- /dev/null +++ b/tools/h4toh5/h4toh5image.c @@ -0,0 +1,861 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +converting an hdf4 image object into an hdf5 dataset, for three component image, this object will be converted into an hdf5 dataset with compound data type. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + +#include "h4toh5main.h" + +/*------------------------------------------------------------------------- + * Function: Image_h4_to_h5 + * + * Purpose: translate Image object into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + ri_id: RI identifier + h5_group: hdf5 group id + h5_palgroup: hdf5 palette group id + + *------------------------------------------------------------------------- + */ + +int Image_h4_to_h5(int32 file_id,int32 ri_id,hid_t h5_group,hid_t h5_palgroup) { + + int32 istat; + int32 ngrattrs; + int32 ncomp; + int check_gloattr; + int32 start[2]; + int32 edges[2]; + int32 dimsizes[2]; + uint16 gr_ref; + int32 image_dtype; + + int check_imagename; + int i; + char image_name[MAX_GR_NAME]; + char grlabel[MAX_GR_NAME]; + char image_class[MAX_GR_NAME]; + char* h5cimage_name; + void* image_data; + HDF_CHUNK_DEF c_def_out; + int32 chunk_dims[2]; + int32 c_flags; + + /* define varibles for hdf5. */ + + hid_t h5ty_id; + hid_t h5memtype; + + hid_t h5_ctype; + hid_t h5_cmemtype; + + hid_t h5d_sid; + hid_t h5dset; + + size_t h4size; + size_t h4memsize; + hsize_t fielddim[1]; + hsize_t h5dims[2]; + herr_t ret; + hid_t create_plist; + + /* zeroing out memory.*/ + + h4toh5_ZeroMemory(image_name,MAX_GR_NAME); + h4toh5_ZeroMemory(image_class,MAX_GR_NAME); + h4toh5_ZeroMemory(grlabel,MAX_GR_NAME); + + /* Obtain information of the image.*/ + + if(GRgetchunkinfo(ri_id,&c_def_out,&c_flags)==FAIL){ + printf("error in getting chunking information. \n"); + return FAIL; + } + + istat = GRgetiminfo(ri_id, image_name, &ncomp, &image_dtype, + NULL, dimsizes, &ngrattrs); + + if(istat == FAIL) { + printf("Cannot obtain GR info. at Image routine.\n"); + return FAIL; + } + + /* data type transferring from hdf4 to hdf5. */ + if(h4type_to_h5type(image_dtype,&h5memtype,&h4memsize, + &h4size,&h5ty_id)== FAIL) { + printf("failed to translate image datatype. \n"); + return FAIL; + } + + /* check whether the datatype is string. */ + if (h5ty_id == H5T_STRING) { + /* rechange string datatype into numerical datatype.*/ + + if(h5string_to_int(image_dtype,&h5memtype,h4memsize, + &h5ty_id)== FAIL) { + printf("error in translating H5T_STRING to int.\n"); + return FAIL; + } + } + + start[0] = 0; + start[1] = 0; + edges[0] = dimsizes[0]; + edges[1] = dimsizes[1]; + + image_data = malloc(h4memsize*dimsizes[0]*dimsizes[1]*ncomp); + + if(image_data == NULL) { + printf("error in allocating memory for image data. \n"); + return FAIL; + } + + istat = GRreadimage(ri_id, start, NULL, edges, (VOIDP)image_data); + + if (istat == FAIL) { + printf("error in reading images.\n"); + free(image_data); + return FAIL; + } + + /* change the order of image dimension: + due to the difference of hdf4 image specification and + hdf5 image specification. */ + + + + h5dims[0] = edges[1]-start[1]; + h5dims[1] = edges[0]-start[0]; + + gr_ref = GRidtoref(ri_id); + if(gr_ref == 0) { + printf("error in obtaining gr reference number. \n"); + free(image_data); + return FAIL; + } + + /* obtaining absolute path of image name.*/ + + check_imagename = -10; + h5cimage_name = get_name(gr_ref,2*num_images,gr_hashtab,&check_imagename); + + if (h5cimage_name == NULL && check_imagename == 0 ) { + printf("error,cannot find image name.\n"); + free(image_data); + return FAIL; + } + + if (h5cimage_name == NULL && check_imagename == -1) { + printf("error,image name is not defined.\n"); + free(image_data); + return FAIL; + } + + if (h5cimage_name == NULL && check_imagename == -2) { + printf("error,not enough memory for get_name. \n"); + free(image_data); + return FAIL; + } + + /**** check number of component of the image object, + and transfer HDF4 object into HDF5 object. ****/ + + if (ncomp <= 0) { + printf("error in obtaining image component\n"); + free(image_data); + free(h5cimage_name); + return FAIL; + } + + /* create property list. */ + + create_plist = H5Pcreate(H5P_DATASET_CREATE); + + if(c_flags == HDF_CHUNK || c_flags == (HDF_CHUNK | HDF_COMP) + || c_flags == (HDF_CHUNK | HDF_NBIT) ){ + + chunk_dims[0] = c_def_out.chunk_lengths[0]; + chunk_dims[1] = c_def_out.chunk_lengths[1]; + + if(H5Pset_chunk(create_plist, 2, (hsize_t *)chunk_dims)<0) { + printf("failed to set up chunking information for "); + printf("property list.\n"); + free(image_data); + H5Pclose(create_plist); + return FAIL; + } + } + if (ncomp == 1) { + + h5d_sid = H5Screate_simple(2,h5dims,NULL); + + if(h5d_sid <0) { + printf("error in creating space for dataset. \n"); + free(image_data); + free(h5cimage_name); + return FAIL; + } + + h5dset = H5Dcreate(h5_group,h5cimage_name,h5ty_id,h5d_sid,create_plist); + + if(h5dset < 0) { + printf("error in creating hdf5 dataset converted from images. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + if (H5Dwrite(h5dset,h5memtype,h5d_sid,h5d_sid,H5P_DEFAULT, + image_data)<0) { + printf("error writing data for hdf5 dataset converted from images.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + } + + else { /* compound datatype. */ + + h5_ctype = H5Tcreate(H5T_COMPOUND,ncomp*h4size); + if (h5_ctype < 0) { + printf("error in generating hdf5 compound data type. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + h5_cmemtype = H5Tcreate(H5T_COMPOUND,ncomp*h4memsize); + if (h5_cmemtype < 0) { + printf("error in generating hdf5 memory compound data type. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + + fielddim[0] = ncomp; + + { + hid_t arr_type; /* Array datatype for inserting fields */ + + /* Create array datatype */ + if((arr_type=H5Tarray_create(h5ty_id,1,fielddim,NULL))<0) { + printf("error creating array datatype.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + ret = H5Tinsert(h5_ctype,"HDF4Image_data",0,arr_type); + if(ret < 0) { + printf("error in inserting array of compound datatype. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + /* Close array datatype */ + if(H5Tclose(arr_type)<0) { + printf("error closing array datatype.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + /* Create array datatype */ + if((arr_type=H5Tarray_create(h5memtype,1,fielddim,NULL))<0) { + printf("error creating array datatype.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + ret = H5Tinsert(h5_cmemtype,"HDF4Image_data",0,arr_type); + if(ret < 0) { + printf("error in inserting array of compound datatype at memory. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + /* Close array datatype */ + if(H5Tclose(arr_type)<0) { + printf("error closing array datatype.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + } + + h5d_sid = H5Screate_simple(2,h5dims,NULL); + if(h5d_sid < 0) { + printf("error in creating space. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + h5dset = H5Dcreate(h5_group,h5cimage_name,h5_ctype,h5d_sid, + create_plist); + if(h5dset < 0) { + printf("error in creating dataset. \n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + + if (H5Dwrite(h5dset,h5_cmemtype,h5d_sid,h5d_sid,H5P_DEFAULT, + (void *)image_data)<0) { + printf("error writing data\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + return FAIL; + } + ret = H5Tclose(h5_ctype); + if(ret < 0) { + printf("error in closing h5_ctype. \n"); + } + ret = H5Tclose(h5_cmemtype); + if(ret <0) { + printf("error in closing h5_cmemtype. \n"); + } + } + +/* convert image annotation into attribute of image dataset. + Since there is no routines to find the exact tag of image object, + we will check three possible object tags of image objects, that is: + DFTAG_RIG,DFTAG_RI,DFTAG_RI8. If the object tag of image object is + falling out of this scope, we will not convert annotations into + hdf5 attributes; it is user's responsibility to make sure object tags + for image objects are only one of the above three tags.*/ + + if(Annoobj_h4_to_h5(file_id,gr_ref,DFTAG_RIG,h5dset)== FAIL){ + printf("failed to convert image annotation into hdf5 attribute.\n"); + free(image_data); + free(h5cimage_name); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(Annoobj_h4_to_h5(file_id,gr_ref,DFTAG_RI,h5dset)== FAIL){ + printf("failed to convert image annotation into hdf5 attribute.\n"); + free(h5cimage_name); + free(image_data); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(Annoobj_h4_to_h5(file_id,gr_ref,DFTAG_RI8,h5dset)== FAIL){ + printf("failed to convert image annotation into hdf5 attribute.\n"); + free(h5cimage_name); + free(image_data); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + + /************************************/ + /* translate GR attributes into HDF5 dataset attribute.*/ + + check_gloattr = 0; + if(gr_tranattrs(ri_id,h5dset,ngrattrs,check_gloattr)==FAIL){ + printf(" cannot obtain attributes. \n"); + free(image_data); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + /* deal with h5dset predefined and user-defined attributes. + Obtain the name and data type and the total number of attributes. + Data attribute at hdf4 is only one-dimensional array. */ + + if (ncomp == 1 && h4size == 1) + strcpy(grlabel,RAST8LABEL); + else if(ncomp == 3 && h4size == 1) + strcpy(grlabel,RAST24LABEL); + else + strcpy(grlabel,GRLABEL); + + strcpy(image_class,IM_CLASS); + + /* transfer hdf4 predefined attributes into hdf5 dataset.*/ + if(h4_transpredattrs(h5dset,HDF4_OBJECT_TYPE,grlabel)==FAIL){ + printf("error in getting hdf4 image type attribute \n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + if(h4_transpredattrs(h5dset,HDF4_OBJECT_NAME,image_name)==FAIL){ + printf("error in getting hdf4 image name attribute. \n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + if(h4_transpredattrs(h5dset,HDF4_IMAGE_CLASS,image_class)==FAIL){ + printf("error in getting hdf4 image class attribute. \n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + gr_ref = GRidtoref(ri_id); + + if(gr_ref == 0) { + printf("error in obtaining reference number of GR.\n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + if(h4_transnumattr(h5dset,HDF4_REF_NUM,gr_ref)==FAIL) { + printf("error in getting hdf4 image number attribute.\n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + /* deal with palette. */ + + if(gr_palette(file_id,ri_id,h5dset,h5_palgroup)== FAIL) { + printf("error in translating palette into h5 dataset.\n"); + H5Pclose(create_plist); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + free(h5cimage_name); + free(image_data); + return FAIL; + } + + ret = H5Pclose(create_plist); + ret = H5Sclose(h5d_sid); + ret = H5Dclose(h5dset); + istat = GRendaccess(ri_id); + free(image_data); + free(h5cimage_name); + return SUCCEED; +} + +/**** palette routine. ****/ +/*------------------------------------------------------------------------- + * Function: gr_palette + * + * Purpose: translate palette into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: HDF4 identifier + ri: raster image id + h5dset: hdf5 dataset + h5_palgroup: hdf5 palette group + + Out: + *------------------------------------------------------------------------- + */ + +int gr_palette(int32 file_id,int32 ri_id,hid_t h5dset,hid_t h5_palgroup) { + + int32 pal_id; + uint16 pal_ref; + char palref_str[MAXREF_LENGTH]; + char palg_name[MAX_GR_NAME]; + char image_index[MAX_GR_NAME]; + int check_pal; + int check_palname; + int pal_stat; + char* h5pal_name=NULL; + + + /* get palette id */ + pal_id = GRgetlutid(ri_id,0); + if(pal_id == FAIL) { + printf("error in obtaining palette id. \n"); + return FAIL; + } + + pal_ref = GRluttoref(pal_id); + + if(pal_ref >0) { + + /* convert reference number into string format. */ + if(conv_int_str(pal_ref,palref_str)==FAIL) { + printf("error in converting palette reference number into string.\n"); + return FAIL; + } + + /* check whether this palette has been looked up already. */ + check_pal = lookup(pal_ref,PAL_HASHSIZE,pal_hashtab); + + if( check_pal < 0) { + printf("error at looking up palette table. \n"); + return FAIL; + } + + /* if check_pal equals to 1, this palette has already been + converted into hdf5 dataset, just obtain the palette name. + if check_pal equals to 0, we will do the converting. */ + + if(check_pal == 1) { + + h5pal_name = get_name(pal_ref,PAL_HASHSIZE,pal_hashtab, + &check_palname); + + if (h5pal_name == NULL && check_palname == 0 ) { + printf("error,cannot find group\n"); + return FAIL; + } + + if (h5pal_name == NULL && check_palname == -1 ) { + printf("error,group name is not defined.\n"); + return FAIL; + } + + } + + if(check_pal == 0) { + /* do converting. */ + strcpy(palg_name,HDF4_PALG); + + /* obtain hdf5 dataset name converted from palette, + no name for hdf4 palette.*/ + h5pal_name = get_obj_aboname(NULL,palref_str,palg_name,HDF4_PALETTE); + if(h5pal_name == NULL) { + printf("error in getting hdf5 palette name.\n"); + return FAIL; + } + + if(set_name(pal_ref,PAL_HASHSIZE,pal_hashtab,h5pal_name)==FAIL) { + printf("error in setting object name.\n"); + free(h5pal_name); + return FAIL; + } + + pal_stat = Palette_h4_to_h5(file_id,pal_id,h5_palgroup,h5pal_name); + + if(pal_stat == FAIL) { + printf("error occurring in transferring palette into dataset. \n"); + free(h5pal_name); + return FAIL; + } + + } + + if(create_pal_objref(h5dset,h5_palgroup,h5pal_name)== FAIL) { + printf("error in creating palette object reference.\n"); + free(h5pal_name); + return FAIL; + } + + if(h5pal_name != NULL) free(h5pal_name); + + strcpy(image_index,HDF4_IMAGE_INDEXED); + if(h4_transpredattrs(h5dset,HDF4_IMAGE_SUBCLASS,image_index)== FAIL) { + printf("failed to transfer hdf4 image indexed.\n"); + return FAIL; + } + } + return SUCCEED; +} +/***** end of palette application. *****/ +/*------------------------------------------------------------------------- + * Function: gr_tranattrs + * + * Purpose: translate attributes of Image object into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + sri_id: RI identifier + sh5_dset: hdf5 dataset + snum_grattrs: number of attribute + check_gloflag: flag to check whether this attribute belongs + to gr interface. + + Out: + *------------------------------------------------------------------------- + */ +int gr_tranattrs(int32 sri_id, hid_t sh5_dset,int snum_grattrs, + int check_gloflag) { + + char sgratrr_name[2*MAX_NC_NAME]; + char grglo[MAX_NC_NAME]; + char* grrepattr_name; + int32 count_sgradata; + int32 sgr_atype; + size_t sh4_amemsize; + size_t sh4_asize; + + hid_t sh5a_sid; + hid_t sh5a_id; + hid_t sh5_atype; + hid_t sh5_amemtype; + hid_t sh5str_type; + hid_t sh5str_memtype; + hsize_t sh5dims[MAX_VAR_DIMS]; + void* sgr_adata; + herr_t sret; + int i; + + + for (i =0;i 0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + +/*convert all objects in group rings into corresponding hdf5 objects. */ + if(h4toh5vgrings(file_id,sd_id,h5_root,h5_dimg,h5_palg) == FAIL){ + printf("error in translating vgroup rings into hdf5 objects.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /*convert all independent lone vdata into corresponding hdf5 datasets with + 2Lockype. */ + if(h4toh5lonevds(file_id,h5_root) == FAIL){ + printf("error in translating lone independent vdata into hdf5 objects.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /*** convert hdf file annotations into hdf5 attributes under the root.***/ + if(Annofil_h4_to_h5(file_id,h5_root) == FAIL) { + printf("error in translating file annotations into root attributes.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /*** deal with untouched sds objects.convert them into hdf5 datasets under root group.***/ + + if(h4toh5unvisitedsds(file_id,sd_id,h5_root,h5_dimg) == FAIL) { + printf("error in converting unvisited sds objects into hdf5 file.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /*** deal with untouched image objects. convert them into hdf5 datasets under root group. ***/ + + if(h4toh5unvisitedimages(file_id,h5_root,h5_palg) == FAIL) { + printf("error in converting unvisited image objects into hdf5 file.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + free_allhashmemory(); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + if(num_sds >0) H5Gclose(h5_dimg); + if(num_images >0) H5Gclose(h5_palg); + H5Gclose(h5_root); + H5Fclose(file5_id); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: get_numof_hdf4obj + * + * Purpose: get number or estimated number of hdf4 objects + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf file identifier + filename: hdf file name + Out: + Modification: + *------------------------------------------------------------------------- + */ +int get_numof_hdf4obj(char*filename,int32 file_id) { + + int32 sd_id;/* sd interface identifer*/ + int32 gr_id;/* gr interface identifer*/ + int num_lonevd;/* number of lone vdata*/ + int num_lonevg;/* number of lone vgroup.*/ + int32 istat; + + estnum_vg = 0; + estnum_vd = 0; + num_sds = 0; + num_images = 0; + num_objects = 0; + + /* obtain number of sds and number of global sds attribute. */ + + sd_id = SDstart(filename,DFACC_READ); + if(sd_id == FAIL) { + printf("error: cannot start SD interface. \n"); + return FAIL; + } + + if(SDfileinfo(sd_id,&num_sds,&num_glsdsattrs) == FAIL) { + printf("error in obtaining SDS information from the file.\n"); + return FAIL; + } + + /* obtain number of images and number of global image attributes.*/ + + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("error in obtaining gr id. \n"); + return FAIL; + } + + if(GRfileinfo(gr_id,&num_images,&num_glgrattrs) == FAIL) { + printf("error in obtaining GR information from the file. \n"); + return FAIL; + } + + /* obtain number of lone vgroup and lone vdata. */ + + istat = Vstart(file_id); + if (istat == FAIL) { + fprintf(stderr, "unable to start hdf4 V interface.\n"); + return FAIL; + } + + num_lonevd = VSlone(file_id,NULL,0); + if(num_lonevd == FAIL) { + printf("error in obtaining lone vdata number. \n"); + return FAIL; + } + + num_lonevg = Vlone(file_id,NULL,0); + if(num_lonevg == FAIL) { + printf("error in obtaining lone vgroup number. \n"); + return FAIL; + } + + /* intelligent guess of the total number of vgroups,total number of + independent vdata. */ + + estnum_vg = 6* num_lonevg; + estnum_vd = 4* num_lonevd; + + /* set the size of name hashtable to num_objects. */ + num_objects = estnum_vg + estnum_vd + num_sds + num_images; + + return SUCCEED; +} + + + +/*------------------------------------------------------------------------- + * Function: set_helpgroups + * + * Purpose: get number or estimated number of hdf4 objects + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + h5root: hdf5 group identifier + h5dimgptr: h5 dimensional group pointer + h5palgptr: h5 palette group pointer + Modification: + *------------------------------------------------------------------------- + */ + +int set_helpgroups(hid_t h5root,hid_t* h5dimgptr,hid_t* h5palgptr){ + + hid_t h5_dimg=(-1);/* hdf5 dimensional scale group identifier. */ + hid_t h5_palg;/* hdf5 palette group identifier. */ + + /*1. dimensional scale group.*/ + + if(num_sds > 0) { + h5_dimg = H5Gcreate(h5root,HDF4_DIMG,0); + if (h5_dimg <0) { + printf("error in creating hdf5 dimensional scale group. \n"); + return FAIL; + } + + *h5dimgptr = h5_dimg; + } + + /*2. palette group.*/ + + if(num_images >0) { + h5_palg = H5Gcreate(h5root,HDF4_PALG,0); + if(h5_palg <0) { + printf("error in creating hdf5 palette group. \n"); + if(h5_dimg>0) H5Gclose(h5_dimg); + return FAIL; + } + + *h5palgptr = h5_palg; + } + + return SUCCEED; + +} + + +/*------------------------------------------------------------------------- + * Function: set_hashtables + * + * Purpose: set up hashtables + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + + Out: + Modification: + *------------------------------------------------------------------------- + */ +int set_hashtables(void) { + + if(num_sds > 0) { + sds_hashtab = malloc(sizeof(struct table)*2*num_sds); + if(init_tab(2*num_sds,sds_hashtab)== FAIL){ + printf("cannot initialize sds hashing table. \n"); + return FAIL; + } + } + + if(num_images > 0) { + gr_hashtab = malloc(sizeof(struct table)*2*num_images); + if(init_tab(2*num_images,gr_hashtab) == FAIL){ + printf("cannot initialize image hashing table. \n"); + return FAIL; + } + } + + /*hashtable is made to be fixed for dimensional scale and palette.*/ + + if(num_sds > 0) { + dim_hashtab = malloc(sizeof(struct name_table)*DIM_HASHSIZE); + if(init_nametab(DIM_HASHSIZE,dim_hashtab) == FAIL) { + printf("can not initialize dimension hashing table.\n"); + return FAIL; + } + } + + /* initialize the palette table */ + if(num_images > 0){ + pal_hashtab = malloc(sizeof(struct table)*PAL_HASHSIZE); + if(init_tab(PAL_HASHSIZE,pal_hashtab) == FAIL) { + printf("can not initialize palette hashing table.\n"); + return FAIL; + } + } + + /* initialize the vgroup table */ + if(estnum_vg > 0) { + vg_hashtab = malloc(sizeof(struct table)*estnum_vg); + } + else { + estnum_vg = VG_DEFHASHSIZE; + vg_hashtab = malloc(sizeof(struct table)*estnum_vg); + } + if(init_tab(estnum_vg,vg_hashtab) == FAIL) { + printf("error in allocating memory for vgroup hashing table.\n"); + return FAIL; + } + + /* initialize the vdata table.*/ + if(estnum_vd > 0) { + vd_hashtab = malloc(sizeof(struct table)*estnum_vd); + } + else { + estnum_vd = VD_DEFHASHSIZE; + vd_hashtab = malloc(sizeof(struct table)*estnum_vd); + } + + if(init_tab(estnum_vd,vd_hashtab)== FAIL) { + printf("cannot initialize vdata hashing table.\n"); + return FAIL; + } + + /* The name hashtable is only for dealing with name clashing, + num_objects is the size of the hash table. */ + + if(num_objects != 0){ + name_hashtab = malloc(sizeof(struct name_table)*num_objects); + if(init_nametab(num_objects,name_hashtab)== FAIL) { + printf("cannot initialize name hashing table. \n"); + return FAIL; + } + } + + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: h4toh5lonevgs + * + * Purpose: Recursively convert hdf4 objects in lone vgroups into + corresponding hdf5 datasets + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : file_id: hdf file id + sd_id: hdf sd interface id + h5group: hdf5 group id + h5_dimg: hdf5 dimensional scale group id + h5_palg: hdf5 palette group id + + Out: + Modification: + *------------------------------------------------------------------------- + */ +int h4toh5lonevgs(int32 file_id,int32 sd_id,hid_t h5group,hid_t h5_dimg,hid_t h5_palg) { + + int32 vgroup_id; + int num_lonevg; /* number of lone vgroup.*/ + int32 *ref_array; + int32 istat; + char vgroup_name[VGNAMELENMAX]; + char* cor_vgroupname; + char vgroup_class[VGNAMELENMAX]; + char refstr[MAXREF_LENGTH]; + int check_vgroup; + int check_tabst; + int lone_vg_number; + char *h5cgroup_name; + + istat = Vstart(file_id); + if (istat == FAIL) { + fprintf(stderr, "unable to start hdf4 V interface.\n"); + return FAIL; + } + + num_lonevg = Vlone(file_id,NULL,0); + + if (num_lonevg == FAIL) { + printf("error in obtaining lone vgroup number. \n"); + return FAIL; + } + + /* obtain object reference array. */ + + /* if no lone vgroup, quit from this function. */ + if(num_lonevg == 0) + return SUCCEED; + + ref_array = (int32 *)malloc(sizeof(int32) *num_lonevg); + + if(ref_array == NULL) { + printf("error in allocating memory for ref_array.\n"); + return FAIL; + } + + num_lonevg = Vlone(file_id,ref_array,num_lonevg); + + /* walk through every lone group in the file */ + + for(lone_vg_number = 0; lone_vg_number < num_lonevg; + lone_vg_number++) { + + vgroup_id = Vattach(file_id,ref_array[lone_vg_number],"r"); + + if(vgroup_id ==FAIL) { + printf("error in attaching lone vgroup.\n"); + free(ref_array); + return FAIL; + } + + /*obtain group name and class name.*/ + h4toh5_ZeroMemory(vgroup_class,VGNAMELENMAX); + istat = Vgetclass(vgroup_id,vgroup_class); + if(istat == FAIL) { + printf("error in getting vgroup class.\n"); + free(ref_array); + Vdetach(vgroup_id); + return FAIL; + } + + h4toh5_ZeroMemory(vgroup_name,VGNAMELENMAX); + istat = Vgetname(vgroup_id,vgroup_name); + if(istat == FAIL ) { + printf("error in getting vgroup name. \n"); + Vdetach(vgroup_id); + free(ref_array); + return FAIL; + } + + /* check for CDF0.0 and RIG0.0, if yes + don't go into this group.*/ + + if(strcmp(vgroup_class,_HDF_CDF)==0) { + Vdetach(vgroup_id); + continue; + } + if(strcmp(vgroup_class,GR_NAME)==0) { + Vdetach(vgroup_id); + continue; + } + + /* converting integer number into string format. */ + if(conv_int_str(ref_array[lone_vg_number],refstr) == FAIL) { + printf("ref. is negative, error in converting\n"); + Vdetach(vgroup_id); + free(ref_array); + return FAIL; + } + + /* checking whether vgroup name contains ORI_SLASH, changing into CHA_SLASH.*/ + cor_vgroupname = correct_name(vgroup_name); + if(cor_vgroupname == NULL) { + printf("error in generating corrected vgroup name. \n"); + Vdetach(vgroup_id); + free(ref_array); + return FAIL; + } + + /* obtaining group name of the converted lone vgroup. In this call, + we will deal with cases such as name clashing and no available vgroup + name. */ + + h5cgroup_name = get_obj_aboname(cor_vgroupname,refstr,NULL,HDF4_VGROUP); + + if(h5cgroup_name == NULL) { + printf("error in getting group name.\n"); + Vdetach(vgroup_id); + free(ref_array); + free(cor_vgroupname); + return FAIL; + } + + /* free memory of corrected name. */ + free(cor_vgroupname); + + /* updating lookup table for vgroups.*/ + + check_vgroup = lookup(ref_array[lone_vg_number],estnum_vg,vg_hashtab); + + if(check_vgroup == 0) { /* adding this vgroup into the list. */ + + check_tabst = set_name(ref_array[lone_vg_number],estnum_vg, + vg_hashtab,h5cgroup_name); + if(check_tabst == FAIL) { + printf("not enough memory to be allocated for vgroup name. \n"); + Vdetach(vgroup_id); + free(h5cgroup_name); + free(ref_array); + return FAIL; + } + } + + /* this line should never fail, if failed, something is wrong with converter or hdf library. */ + + if(check_vgroup == 1){ + fprintf(stderr,"this vgroup should not be touched. \n"); + Vdetach(vgroup_id); + free(h5cgroup_name); + free(ref_array); + return FAIL; + } + + if(Vgroup_h4_to_h5(file_id,vgroup_id,sd_id,h5group,h5_dimg,h5_palg)==FAIL){ + printf("error in translating vgroup into hdf5 objects.\n"); + Vdetach(vgroup_id); + free(h5cgroup_name); + free(ref_array); + return FAIL; + } + + Vdetach(vgroup_id); + free(h5cgroup_name); + } + free(ref_array); + return SUCCEED; +} + + + +/*------------------------------------------------------------------------- + * Function: h4toh5vgrings + * + * Purpose: Recursively convert objects at special hdf4 vgroups + (vgroup rings) + into objects of corresponding hdf5 groups. The strategy here + is to arbitrily grab any vgroup in the group ring and put it + under hdf5 root. + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : file_id: hdf file id + sd_id: hdf sds id + h5group: hdf5 group id + h5_dimg: hdf5 dimensional scale group id + h5_palg: hdf5 palette group id + + Out: + Modification: + *------------------------------------------------------------------------- + */ + +int h4toh5vgrings(int32 file_id,int32 sd_id,hid_t h5group,hid_t h5_dimg,hid_t h5_palg){ + + int32 vgroup_id; + int32 ref_num; + char vgroup_name[VGNAMELENMAX]; + char* cor_vgroupname; + char vgroup_class[VGNAMELENMAX]; + char refstr[MAXREF_LENGTH]; + int check_vgroup; + int32 istat; + char *h5cgroup_name; + + ref_num = Vgetid(file_id,-1); + + while (ref_num != -1) { + + /* if we find a group that is not touched, grab it under root group.*/ + + check_vgroup = lookup(ref_num,estnum_vg,vg_hashtab); + + if (check_vgroup == 0){ + + vgroup_id = Vattach(file_id,ref_num,"r"); + if(vgroup_id ==FAIL) { + printf("error in attaching group in a group ring. \n"); + return FAIL; + } + + h4toh5_ZeroMemory(vgroup_name,VGNAMELENMAX); + istat = Vgetname(vgroup_id,vgroup_name); + if(istat ==FAIL) { + printf("error in obtaining vgroup names. \n"); + Vdetach(vgroup_id); + return FAIL; + } + + h4toh5_ZeroMemory(vgroup_class,VGNAMELENMAX); + if(Vgetclass(vgroup_id,vgroup_class) == FAIL) { + printf("error in obtaining vgroup class name. \n"); + Vdetach(vgroup_id); + return FAIL; + } + + /* do nothing for those predefined attribute.*/ + + if(vgroup_class[0] != '\0') { + + if(strcmp(vgroup_class,_HDF_ATTRIBUTE)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,_HDF_VARIABLE)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,_HDF_DIMENSION)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,_HDF_UDIMENSION)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,_HDF_CDF)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,GR_NAME)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + + if(strcmp(vgroup_class,RI_NAME)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + } + + if(vgroup_name[0] != '\0') { + if(strcmp(vgroup_name,GR_NAME)==0) { + ref_num = Vgetid(file_id,ref_num); + Vdetach(vgroup_id); + continue; + } + } + + /* convert reference number into string format. */ + if(conv_int_str(ref_num,refstr) == FAIL) { + printf("ref. is negative, error in converting\n"); + Vdetach(vgroup_id); + return FAIL; + } + + /* checking whether vgroup name contains ORI_SLASH, changing into CHA_SLASH.*/ + cor_vgroupname = correct_name(vgroup_name); + if(cor_vgroupname == NULL) { + printf("error in generating corrected vgroup name. \n"); + Vdetach(vgroup_id); + return FAIL; + } + /* obtain the hdf5 group name. */ + h5cgroup_name = get_obj_aboname(cor_vgroupname,refstr,NULL,HDF4_VGROUP); + + if(h5cgroup_name == NULL) { + printf("error in getting vgroup name.\n"); + Vdetach(vgroup_id); + free(cor_vgroupname); + return FAIL; + } + + free(cor_vgroupname); + if(set_name(ref_num,estnum_vg,vg_hashtab,h5cgroup_name)==FAIL) { + printf("error in setting h5 group name.\n"); + Vdetach(vgroup_id); + free(h5cgroup_name); + return FAIL; + } + + if(Vgroup_h4_to_h5(file_id,vgroup_id,sd_id,h5group,h5_dimg,h5_palg) + ==FAIL){ + + printf("error in translating vgroup into hdf5 group\n"); + Vdetach(vgroup_id); + free(h5cgroup_name); + return FAIL; + } + + Vdetach(vgroup_id); + free(h5cgroup_name); + } + ref_num = Vgetid(file_id,ref_num); + } + return SUCCEED; + +} + + +/*------------------------------------------------------------------------- + * Function: h4toh5lonevds + * + * Purpose: convert hdf4 lone vdata into + the corresponding hdf5 datasets + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : file_id: hdf file id + h5group: hdf5 group id + + Out: + Modification: + *------------------------------------------------------------------------- + */ +int h4toh5lonevds(int32 file_id, hid_t h5group){ + + int32 vdata_id; + int32 *ref_vdata_array; + int32 vdata_tag; + int32 vdata_ref; + int32 istat; + char vdata_name[VGNAMELENMAX]; + char* cor_vdataname; + char vdata_class[VGNAMELENMAX]; + char refstr[MAXREF_LENGTH]; + int check_vdata; + int lone_vd_number; + int num_lonevd; + char *h5cvdata_name; + + num_lonevd = VSlone(file_id,NULL,0); + + if (num_lonevd == FAIL) { + printf("error in obtaining lone vgroup number. \n"); + return FAIL; + } + + if (num_lonevd > 0) { + + ref_vdata_array = (int32 *)malloc(sizeof(int32) *(num_lonevd)); + + num_lonevd = VSlone(file_id,ref_vdata_array,num_lonevd); + + if(num_lonevd == FAIL) { + printf("error in obtaining lone vdata number the second time.\n"); + free(ref_vdata_array); + } + /* walk through all lone vdatas. */ + + for(lone_vd_number = 0; lone_vd_number < num_lonevd;lone_vd_number++) + { + vdata_id = VSattach(file_id,ref_vdata_array[lone_vd_number],"r"); + + if(vdata_id == FAIL) { + printf("error in obtaining vdata id for lone vdata.\n"); + free(ref_vdata_array); + } + + /* Make sure this vdata is not an attribute of other hdf4 objects.*/ + + if(!VSisattr(vdata_id)) { + + h4toh5_ZeroMemory(vdata_class,VGNAMELENMAX); + istat = VSgetclass(vdata_id,vdata_class); + if(istat == FAIL) { + printf("error in getting vdata class name.\n"); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + + + if(!strncmp(vdata_class,_HDF_CHK_TBL_CLASS,strlen(_HDF_CHK_TBL_CLASS))){ + + VSdetach(vdata_id); + continue; + } + + vdata_ref = VSQueryref(vdata_id); + + if(vdata_ref == FAIL) { + printf("error in getting vdata reference number.\n"); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + + vdata_tag = VSQuerytag(vdata_id); + if(vdata_tag == FAIL){ + printf("error in getting vdata tag.\n"); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + + + h4toh5_ZeroMemory(vdata_name,VGNAMELENMAX); + istat = VSQueryname(vdata_id,vdata_name); + + if(istat == FAIL) { + printf("error in getting vdata name. \n"); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + + /* converting reference number into string format.*/ + if(conv_int_str(ref_vdata_array[lone_vd_number],refstr)==FAIL) { + printf("error in converting int to string.\n"); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + /* checking whether vdata name contains ORI_SLASH, changing into CHA_SLASH.*/ + cor_vdataname = correct_name(vdata_name); + if(cor_vdataname == NULL) { + printf("error in generating corrected vgroup name. \n"); + VSdetach(vdata_id); + free(ref_vdata_array); + return FAIL; + } + /* obtaining hdf5 dataset name that is converted from hdf4 vdata.*/ + h5cvdata_name = get_obj_aboname(cor_vdataname,refstr,NULL,HDF4_VDATA); + if(h5cvdata_name == NULL) { + printf("error in getting vdata name.\n"); + free(ref_vdata_array); + VSdetach(vdata_id); + free(cor_vdataname); + return FAIL; + } + + free(cor_vdataname); + check_vdata = lookup(ref_vdata_array[lone_vd_number],estnum_vd, + vd_hashtab); + + /* check_vdata should be 1, if it is 1, either converter or hdf lib has bugs. */ + if(check_vdata == 1){ + printf("lone vdata should not be checked before.\n"); + free(h5cvdata_name); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + + if(set_name(ref_vdata_array[lone_vd_number],estnum_vd,vd_hashtab, + h5cvdata_name)==FAIL) { + printf("error in setting lone vdata name. \n"); + free(ref_vdata_array); + free(h5cvdata_name); + VSdetach(vdata_id); + return FAIL; + } + + if(Vdata_h4_to_h5(file_id,vdata_id,h5group)== FAIL) { + printf("error in translating independent vdata into"); + printf(" hdf5 datasets.\n"); + free(h5cvdata_name); + free(ref_vdata_array); + VSdetach(vdata_id); + return FAIL; + } + free(h5cvdata_name); + } + + VSdetach(vdata_id); + } + free(ref_vdata_array); + } + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: h4toh5unvisitedsds + * + * Purpose: convert unvisited sds objects into hdf5 datasets and put these + datasets under hdf5 root group + This routine will cover old hdf file that doesn't have vgroups. + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + sd_id: hdf sds id + h5root: hdf5 root id + h5_dimg: hdf5 dimensional scale group id + + Out: + Modification: + *------------------------------------------------------------------------- + */ + + +int h4toh5unvisitedsds(int32 file_id,int32 sd_id,hid_t h5root,hid_t h5_dimg) { + + int i; + int32 sds_id;/* sd dataset identifer*/ + int32 sds_rank;/* sds dataset dimension rank.*/ + int32 sds_dimsizes[DIM_HASHSIZE];/* array that contains the size of the each dimension in sds dataset.*/ + int32 sds_dtype;/*sds dataset datatype.*/ + int32 num_sdsattrs;/* number of sds attributes. */ + char sds_name[MAX_NC_NAME];/* sds name.*/ + char* cor_sdsname; + int32 obj_ref; /* obj reference number assigned to sds and images.*/ + char refstr[MAXREF_LENGTH];/*object reference number in character string format.*/ + int check_sds;/* flag to check whether this sds is visited. 1 for visited and 0 for non-visited.*/ + char *h5csds_name;/* absolute path name of hdf5 dataset transferred from old sds.*/ + + if(sd_id == FAIL) { + printf("error: cannot start SD interface. \n"); + return FAIL; + } + + /* check all sds objects. */ + for(i=0;ist_mode); +} + +/***************************************************************************** + + Routine: BuildFilename() + + Description: Build a filename with new extension + + Input: filename - present filename + ext - extension to root of filename + + Output: (filename:r).ext + +*****************************************************************************/ + +char *BuildFilename(char *filename, char *ext) +{ + /* build outgoing filename */ + + char *filename_out; + char *lastper_ptr, *lastdir_ptr; + int root_len; + + lastper_ptr = strrchr(filename,'.'); + lastdir_ptr = strrchr(filename,'/'); + + if ( lastper_ptr <= lastdir_ptr ) { /* no extension */ + root_len = strlen(filename); + } else { /* existing extension */ + root_len = (int)(lastper_ptr - filename); + } + + filename_out = (char *)HDmalloc(root_len + strlen(ext) + 2); + filename_out = strncpy(filename_out, filename, (size_t)root_len); + filename_out[root_len] = '\0'; + filename_out = strcat(filename_out,"."); + filename_out = strcat(filename_out,ext); + + return filename_out; +} + + +/***************************************************************************** + + Routine: PrintOptions_h4toh5() + + Description: This routine prints the acceptable argument formats out to stderr. + + Input: None + + Output: output to stderr + +*****************************************************************************/ + +void PrintOptions_h4toh5(void) +{ + fprintf(stderr,"\nUsage: "); + fprintf(stderr,"\n h4toh5 -h (gives this print-out)\n"); + fprintf(stderr," h4toh5 input.hdf output.h5\n"); + fprintf(stderr," h4toh5 input.hdf\n"); +} + + + + + diff --git a/tools/h4toh5/h4toh5main.h b/tools/h4toh5/h4toh5main.h new file mode 100644 index 0000000..2bb6c88 --- /dev/null +++ b/tools/h4toh5/h4toh5main.h @@ -0,0 +1,109 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + +Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +including declarations of subroutines of all .c files excluding h4toh5util.c. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + + +#ifndef H4TOH5MAIN_H +#define H4TOH5MAIN_H +#include "hdf.h" +#include "mfhdf.h" +#include "hdf5.h" +#include "h4toh5util.h" +#include +#include +#endif + +/* For windows support.*/ +#if WIN32 +typedef unsigned int mode_t; +#endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode)&0xF000) == S_IFDIR) +#endif + +/* subroutines to check initial settings and inputting parameters. +Adapted from h5toh4 tools and used for h4toh5main.c */ + +void PrintOptions_h4toh5(void); +int test_file(char *filename,int oflag,mode_t mode); +int test_dir(char *); +char *BuildFilename(char *filename, char *ext); + +/* subroutines for h4toh5main.c */ +int h4toh5(char*,char*); +int get_numof_hdf4obj(char*,int32); +int set_hashtables(void); +int set_helpgroups(hid_t,hid_t*,hid_t*); +int h4toh5lonevds(int32,hid_t); +int h4toh5lonevgs(int32,int32,hid_t,hid_t,hid_t); +int h4toh5vgrings(int32,int32,hid_t,hid_t,hid_t); +int h4toh5unvisitedimages(int32,hid_t,hid_t); +int h4toh5unvisitedsds(int32,int32,hid_t,hid_t); +void free_allhashmemory(void); + +/*subroutines for h4toh5vgroup.c*/ + +int Vgroup_h4_to_h5(int32,int32,int32,hid_t,hid_t,hid_t); +int convert_vgroup(int32,int32, int32,char* ,hid_t,hid_t,hid_t); +int convert_vdata(int32,int32,char*,hid_t); +int convert_sds(int32,int32,int32,char*,hid_t,hid_t); +int convert_image(int32,int32,char*,hid_t,hid_t); + +/*subroutines for h4toh5vdata.c*/ + +int Vdata_h4_to_h5(int32,int32,hid_t); +int vdata_transattrs(int32,hid_t,int,int,char*); +int gen_h5comptype(int32,int32,size_t *,size_t*,hid_t*,hid_t*,hid_t,hid_t); + +/* subroutines for h4toh5sds.c*/ +int Sds_h4_to_h5(int32,int32,hid_t,hid_t); +int sds_transattrs(int32, hid_t,int,int); +int sdsdim_to_h5dataset(int32,int32,hid_t,hid_t,int32); + + +/*subroutines for h4toh5image.c*/ +int Image_h4_to_h5(int32,int32,hid_t,hid_t); +int gr_tranattrs(int32, hid_t,int,int); +int gr_palette(int32,int32,hid_t,hid_t); +int create_pal_objref(hid_t ,hid_t ,char *); + +/*subroutines for h4toh5anno.c*/ +char* trans_tag_name(int32,ann_type); +int Annofil_h4_to_h5(int32,hid_t); +int Annoobj_h4_to_h5(int32,int32,int32,hid_t); + +/*subroutines for h4toh5pal.c*/ +int Palette_h4_to_h5(int32,int32 ,hid_t,char *); + + + + + + + diff --git a/tools/h4toh5/h4toh5pal.c b/tools/h4toh5/h4toh5pal.c new file mode 100644 index 0000000..556ecdc --- /dev/null +++ b/tools/h4toh5/h4toh5pal.c @@ -0,0 +1,202 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +Converting an hdf4 palette object into a hdf5 dataset. +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + +#include "h4toh5main.h" + + +/*------------------------------------------------------------------------- + * Function: Palette_h4_to_h5 + * + * Purpose: translate palette into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: file id + pal_id: PALETTE identifier + h5_g: hdf5 group id + pal_name: path name of the group where all palettes are in + + *------------------------------------------------------------------------- + */ + +int Palette_h4_to_h5(int32 file_id,int32 pal_id,hid_t h5g,char*pal_name) { + + int32 ncomp; + int32 pal_ref; + int32 pal_type; + int32 interlace_mode; + int32 num_entries; + void* pal_data; + size_t h4memsize; + size_t h4size; + + char palette_label[MAX_PAL_NAME]; + char palette_class[MAX_PAL_NAME]; + char palette_type[MAX_PAL_NAME]; + char palette_colormodel[MAX_PAL_NAME]; + + hid_t h5memtype; + hid_t h5type; + hid_t h5d_sid; + hid_t h5dset; + hsize_t h5dims[2]; + + pal_ref = GRluttoref(pal_id); + + if(pal_ref <0) { + printf("error in obtaining palette.\n"); + return FAIL; + } + + /* no palette, just return. */ + if(pal_ref == 0) return SUCCEED; + + if(GRgetlutinfo(pal_id,&ncomp,&pal_type,&interlace_mode,&num_entries)==FAIL) { + printf("error in getting palette information.\n"); + return FAIL; + } + + if(h4type_to_h5type(pal_type,&h5memtype,&h4memsize,&h4size,&h5type)== FAIL) { + fprintf(stderr,"failed to translate image datatype. \n"); + return FAIL; + } + + /* according to mapping document, data type for palette will always be + uint8. */ + + if (h5type == H5T_STRING) { + if(h5string_to_int(pal_type,&h5memtype,h4memsize,&h5type)==FAIL) { + fprintf(stderr,"failed to translate H5T_STRING to int8."); + return FAIL; + } + } + + h5dims[0] = num_entries; + h5dims[1] = ncomp; + + pal_data = malloc(h4memsize*ncomp*num_entries); + + if (pal_data == NULL) { + printf("error in allocating memory for palette data.\n"); + return FAIL; + } + + if (GRreadlut(pal_id,(VOIDP)pal_data)==FAIL) { + printf("error in reading palette data. \n"); + free(pal_data); + return FAIL; + } + + h5d_sid = H5Screate_simple(2,h5dims,NULL); + + if (h5d_sid <0) { + printf("error in creating space.\n"); + free(pal_data); + return FAIL; + } + + h5dset = H5Dcreate(h5g,pal_name,h5type,h5d_sid,H5P_DEFAULT); + + if (h5dset < 0) { + printf("error in creating dataset. \n"); + free(pal_data); + H5Sclose(h5d_sid); + return FAIL; + } + + if (H5Dwrite(h5dset,h5memtype,h5d_sid,h5d_sid,H5P_DEFAULT, + (void *)pal_data)<0) { + fprintf(stdout,"error writing data for palette data\n"); + free(pal_data); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + free(pal_data); + + + strcpy(palette_label,PALABEL); + strcpy(palette_class,PALETTE); + strcpy(palette_type,PAL_TYPE); + strcpy(palette_colormodel,RGB); + /* convert palette annotation into attribute of palette dataset. + Since there are no routines to find the exact tag of palette object, + we will check three possible object tags of palette objects, that is: + DFTAG_LUT. If the object tag of palette object is + falling out of this scope, we will not convert annotations into + hdf5 attributes; it is user's responsibility to make sure that object tags + for palette objects are DFTAG_LUT.*/ + + if(Annoobj_h4_to_h5(file_id,pal_ref,DFTAG_LUT,h5dset)== FAIL){ + printf("failed to convert palette annotation into hdf5 attribute.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(h4_transpredattrs(h5dset,HDF4_OBJECT_TYPE,palette_label)==FAIL) { + printf("unable to transfer palette label to HDF4 OBJECT TYPE.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(h4_transpredattrs(h5dset,HDF4_PALETTE_CLASS,palette_class)==FAIL){ + printf("unable to transfer palette class to HDF4 PALETTE CLASS.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(h4_transpredattrs(h5dset,HDF4_PALETTE_TYPE,palette_type)==FAIL){ + printf("unable to transfer palette type to HDF4 PALETTE TYPE.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + + if(h4_transpredattrs(h5dset,PAL_COLORMODEL,palette_colormodel)==FAIL){ + printf("unable to transfer palette type to HDF4 PALETTE TYPE.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + if(h4_transnumattr(h5dset,HDF4_REF_NUM,pal_ref)==FAIL) { + printf("unable to transfer palette reference number to HDF4 REF. NUM.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + return FAIL; + } + return SUCCEED; +} + + + + + diff --git a/tools/h4toh5/h4toh5sds.c b/tools/h4toh5/h4toh5sds.c new file mode 100644 index 0000000..89e5ddf --- /dev/null +++ b/tools/h4toh5/h4toh5sds.c @@ -0,0 +1,1096 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +Converting an hdf4 sds object into an hdf5 dataset. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + +#include "h4toh5main.h" + +/*------------------------------------------------------------------------- + * Function: Sds_h4_to_h5 + * + * Purpose: translate SDS object into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + sds_id: SDS identifier + h5_group: hdf5 group id + h5_dimgroup: hdf5 dimension group id + dim_pathname: dimensional path name + + *------------------------------------------------------------------------- + */ + +int Sds_h4_to_h5(int32 file_id,int32 sds_id,hid_t h5_group,hid_t h5_dimgroup){ + + int32 sds_dtype; + int32 sds_rank; + int32 sds_dimsizes[MAX_VAR_DIMS]; + int32* sds_start; + int32* sds_edge; + int32* sds_stride; + int32 count_sdsdata; + int32 sds_ref; + intn sds_empty; + int32 istat; + int i; + int32 num_sdsattrs; + void* sds_data; + + int check_sdsname; + int check_gloattr; + + char sdsname[MAX_NC_NAME]; + char sdslabel[MAX_NC_NAME]; + size_t h4size; + size_t h4memsize; + HDF_CHUNK_DEF c_def_out; + hsize_t* chunk_dims; + int32 c_flags; + + /* define varibles for hdf5. */ + + hid_t h5dset; + hid_t h5d_sid; + hid_t h5ty_id; + hid_t h5_memtype; + hid_t create_plist; + hsize_t h5dims[MAX_VAR_DIMS]; + hsize_t max_h5dims[MAX_VAR_DIMS]; + + char* h5csds_name; + + herr_t ret; + /* zeroing out the memory for sdsname and sdslabel.*/ + + h4toh5_ZeroMemory(sdsname,MAX_NC_NAME); + h4toh5_ZeroMemory(sdslabel,MAX_NC_NAME); + /* check whether the sds is empty. */ + + if(SDcheckempty(sds_id,&sds_empty)== FAIL) { + printf("error in running SDcheckempty routine. \n"); + return FAIL; + } + + if(sds_empty != 0) return SUCCEED; + + + /*check whether the sds is created with unlimited dimension. */ + + if(SDgetchunkinfo(sds_id,&c_def_out, &c_flags)== FAIL) { + printf("error in getting chunking information. \n"); + return FAIL; + } + + /*obtain name,rank,dimsizes,datatype and num of attributes of sds */ + if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype, + &num_sdsattrs)==FAIL) { + printf("unable to get information of sds h5dset.\n"); + return FAIL; + } + + /* obtain start,edge, stride and number of sds data. */ + + sds_start = malloc(sizeof(int32)*sds_rank); + if(sds_start == NULL) { + printf("error in allocating memory for sds start.\n"); + return FAIL; + } + + sds_edge = malloc(sizeof(int32)*sds_rank); + if(sds_edge == NULL) { + printf("error in allocating memory for sds edge.\n"); + free(sds_start); + return FAIL; + } + + sds_stride = malloc(sizeof(int32)*sds_rank); + if(sds_stride == NULL) { + printf("error in allocating memory for sds stride. \n"); + free(sds_start); + free(sds_edge); + return FAIL; + } + + count_sdsdata = 1; + for (i=0;i + + +#define FILESDS1 "sds_typ_test.hdf" +#define FILESDS2 "sds_dim_test.hdf" +#define FILESDS3 "sds_attr_test.hdf" +#define FILEGR "gr_typ_test.hdf" +#define FILERAS8 "ras_8_test.hdf" +#define FILERAS24 "ras_24_test.hdf" +#define FILEGRPAL "image_attr_test.hdf" +#define FILEVD "vdata_test.hdf" +#define FILECLASHVG "vgnameclash_test.hdf" +#define FILECLASHSDS "sdsnameclash_test.hdf" +#define FILECLASHVD "vdnameclash_test.hdf" +#define FILECLASHGR "grnameclash_test.hdf" +#define FILELOOP "vg_loop_test.hdf" +#define FILEHL "vg_hl_test.hdf" +#define FILEVG "vg_all_test.hdf" +#define FILEANNO "anno_test.hdf" + +/* for testing sds*/ +#define TYP_RANK 3 +#define TYP_DIMSIZE 4 +#define INT8_UPLIMIT 0x7E +#define UINT8_UPLIMIT 0xFC +#define INT16_UPLIMIT 0x7FFE +#define UINT16_UPLIMIT 0xFFFC +#define INT32_UPLIMIT 0x7FFFFFFE +#define UINT32_UPLIMIT 0xFFFFFFFC +#define ATT_SIZE 10 + +/* for testing image*/ +#define X_LENGTH 10 +#define Y_LENGTH 5 +#define NUM_COLORS 256 +#define F_ATT1_NAME "File Attribute" +#define RI_ATT1_NAME "Image Attribute" +#define F_ATT1_VAL "Contents of First FILE Attribute" +#define F_ATT1_N_VALUES 32 +#define RI_ATT1_VAL "Contents of IMAGE's First Attribute" +#define RI_ATT1_N_VALUES 35 + +/* for testing vdata*/ +#define NRECORDS 10 +#define FIELD_1 "Temp" +#define FIELD_2 "Height" +#define FIELD_3 "Speed" +#define FIELD_4 "Ident" +#define FIELD_5 "Position" +#define FIELD_NAMES "Temp,Height,Speed,Ident,Position" +#define FIELD_VDNAMES "Temp,Height" + +/*for testing vgroup*/ +#define VGATTR_NAME "Vgroup attribute 1" +int test_sdstyp(void); +int test_sdsdim(void); +int test_sdsattr(void); +int test_grtyp(void); +int test_ras8(void); +int test_ras24(void); +int test_imageattr(void); +int test_vdata(void); +int test_vgnameclash(void); +int test_sdsnameclash(void); +int test_grnameclash(void); +int test_vdnameclash(void); +int test_vgloop(void); +int test_vghl(void); +int test_vgall(void); +int test_anno(void); + +int main(void) { + if(test_sdstyp()== FAIL) { + printf("failed to create sds_typ_test.hdf file.\n"); + return FAIL; + } + if(test_sdsdim()== FAIL) { + printf("failed to create sds_dim_test.hdf file. \n"); + return FAIL; + } + if(test_sdsattr()== FAIL) { + printf("failed to create sds_attr_test.hdf file. \n"); + return FAIL; + } + if(test_grtyp()==FAIL) { + printf("failed to create gr_typ_test.hdf file. \n"); + return FAIL; + } + + if(test_ras8()==FAIL) { + printf("failed to create ras8_test.hdf file.\n"); + return FAIL; + } + + if(test_ras24()==FAIL) { + printf("failed to create ras24_test.hdf file.\n"); + return FAIL; + } + if(test_imageattr()== FAIL) { + printf("failed to create image_attr_test.hdf file.\n"); + return FAIL; + } + + if(test_vdata()== FAIL) { + printf("failed to create vdata_test.hdf file.\n"); + return FAIL; + } + + if(test_vgnameclash()==FAIL) { + printf("failed to create vg_nameclash.hdf file.\n"); + return FAIL; + } + + if(test_sdsnameclash()==FAIL) { + printf("failed to create sds_nameclash.hdf file.\n"); + return FAIL; + } + + if(test_grnameclash()==FAIL) { + printf("failed to create gr_nameclash.hdf file. \n"); + return FAIL; + } + + if(test_vdnameclash()==FAIL) { + printf("failed to create vd_nameclash.hdf file.\n"); + return FAIL; + } + if(test_vgloop()==FAIL) { + printf("failed to create vg_loop.hdf file. \n"); + return FAIL; + } + if(test_vghl()==FAIL) { + printf("failed to create vg_hl.hdf file. \n"); + return FAIL; + } + if(test_vgall()==FAIL) { + printf("failed to create vg_all.hdf file. \n"); + return FAIL; + } + if(test_anno()==FAIL) { + printf("failed to create vg_anno.hdf file. \n"); + return FAIL; + } + return 0; +} + +/* this subroutine will hdf file with typical sds objects, + + The rank is TYP_RANK, each dimensional size is TYP_DIMSIZE. + Datatype we are testing is: + char, + int8, + int16, + int32, + uint16, + uint32, + lint16, + lint32, + luint32, + float32, + float64, + +*/ +int test_sdstyp(){ + + int32 file_id,sds_id; + int32 i,j,k; + int32 typ_start[TYP_RANK],typ_edges[TYP_RANK],typ_stride[TYP_RANK]; + char8 typchar_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int8 typint8_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int16 typint16_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 typint32_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + uint16 typuint16_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 typlint32_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + uint32 typluint32_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + float32 typfloat32_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + float64 typfloat64_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + float64 typlfloat64_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 typ_dims[TYP_RANK]; + int32 CUB_SIZE; + int istat; + /* TYPICAL sds array, we limit the dimensional size for testing purpose. */ + + CUB_SIZE = (TYP_DIMSIZE-1)*(TYP_DIMSIZE-1)*(TYP_DIMSIZE-1); + + /* 1. data type is char */ + for (i=0;ivb and vb->va */ + +int test_vgloop() { + + int32 file_id, vgroupa_ref, vgroupa_id, vgroupb_ref,vgroupb_id; + int32 istat,dims[TYP_RANK]; + int i,j,k; + + /*2. for sds */ + int32 sd_id,sds_id; + int32 sds_ref; + int32 array_data[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 start[TYP_RANK],edges[TYP_RANK],stride[TYP_RANK]; + + + for (i=0;inext){ + if (np->ref == objref){ + return 1; + } + } + return 0; +} + +/*------------------------------------------------------------------------- + * Function: init_tab + * + * Purpose: this function will initialize the hash table. + * + + * Return: SUCCEED, table is initialzed. FAIL,otherwise. + * + * In : + SIZE: the hashtable SIZE. + hashtab: pointer to the hash table. + + *------------------------------------------------------------------------- + */ + +int init_tab(int SIZE,struct table *hashtab) { + + int i; + if(hashtab == NULL) { + printf("memory for hashing table is not allocated.\n"); + return FAIL; + } + for (i = 0;i < SIZE; i++) { + (hashtab+i%SIZE)->ref = -1; + (hashtab+i%SIZE)->next = NULL; + (hashtab+i%SIZE)->name = NULL; + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: init_nametab + * + * Purpose: this function will initialize the name hash table. + * + + * Return: SUCCEED, table is initialzed. FAIL,otherwise. + * + * In : + SIZE: the hashtable SIZE. + name_hashtab: pointer to the hash table. + + *------------------------------------------------------------------------- + */ +int init_nametab(int SIZE, struct name_table * name_hashtab) { + + int i; + + if(name_hashtab == NULL) { + printf("cannot allocate memory for name hashing table.\n"); + return FAIL; + } + for (i=0;i < SIZE; i++) { + (name_hashtab+i%SIZE)->name = NULL; + (name_hashtab+i%SIZE)->next = NULL; + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: get_name + * + * Purpose: obtain the name of the object + * + * Return: the object name + * + * In : objref: reference number of the current object. + SIZE: the hashtable SIZE. + hashtab: pointer to the hash table + pcheck_get: a flag to check errors + + *------------------------------------------------------------------------- + */ + +char* get_name(int objref,int SIZE,struct table*hashtab, int* pcheck_get) { + + struct table *np; + char* tempname; + + np = hashtab+objref%SIZE; + + for (np = hashtab+objref%SIZE; np!=NULL;np=np->next){ + + if (np->ref==objref){ + + if (np->name == NULL) { + *pcheck_get = -1; + return NULL; + } + + else { + tempname = malloc(strlen(np->name)+1); + if(tempname == NULL) { + *pcheck_get = -2; + return NULL; + } + strcpy(tempname,np->name); + return tempname; + } + } + } + + *pcheck_get = 0; + return NULL; +} + + +/*------------------------------------------------------------------------- + * Function: set_name + * + * Purpose: store the name of the object into the hash table + * + * Return: SUCCEED: the name is either set before or set in this routine + * FAIL: the name is not set properly + * + * In : objref: reference number of the current object + SIZE: the hashtable SIZE + hashtab: hash table + namein: object name + + *------------------------------------------------------------------------- + */ + + +int set_name(int objref,int SIZE,struct table*hashtab, char* namein) { + + struct table *np; + struct table *temptr; + + temptr = malloc(sizeof(struct table)); + if(temptr == NULL) { + printf("not enough memory to be allocated. \n"); + return FAIL; + } + + np = hashtab+objref%SIZE; + if(namein == NULL) { + printf("error in inputting name into the table.\n"); + return FAIL; + } + + for (np = hashtab+objref%SIZE; np!= NULL;np = np->next){ + if (np->ref==objref){ + /* the name is set already, don't do anything.*/ + return SUCCEED; + } + if (np->next == NULL) { + np->next = temptr; + temptr->ref = objref; + temptr->next = NULL; + temptr->name = malloc(strlen(namein)+1); + if(temptr->name == NULL) { + printf("error in allocating memory. \n"); + return FAIL; + } + strcpy(temptr->name,namein); + return SUCCEED; + } + } + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: lookup_name + * + * Purpose: 1. look up whether the same name is used for different objects + 2. then update the table + * + * Return: 1, if the name is in the name hash table. + 0, if the name is to be added into the name table. + -1, otherwise. + * + * In : + size: the hashtable SIZE. + nametab: name hash table + name: the name to be looked up + + *------------------------------------------------------------------------- + */ + +int lookup_name(char* name, int size,struct name_table *nametab) { + + /* temporary pointer of the name table that points to the beginning + address of the current bucket.*/ + struct name_table *np; + + /* temporary pointer of the added name table.*/ + struct name_table *temptr; + + if(name == NULL) { + printf("the name to be looked up is NULL.\n"); + return -1; + } + + temptr = malloc(sizeof(struct name_table)); + if(temptr == NULL) { + printf("not enough memory to be allocated. \n"); + return -1; + } + + if(nametab == NULL) { + printf("no name_table for this category of objects.\n"); + return -1; + } + np = nametab+hash_fun(name,size); + + temptr->name = malloc(strlen(name)+1); + if(temptr->name == NULL) { + printf("not enough memory to be allocated to table name.\n"); + return -1; + } + + /* look through the linked list starting from the current bucket. + If the name is found, return 1, otherwise, return 0 + after inserting the new bucket. */ + + for(np = nametab+hash_fun(name,size); np!= NULL;np = np->next) { + if(np->name == NULL) { + np->name = malloc(strlen(name)+1); + if(np->name == NULL) { + printf("cannot allocate memory for object name.\n"); + return -1; + } + strcpy(np->name,name); + free(temptr->name); + free(temptr); + return 0; + } + if(strcmp(name,np->name)==0){ + free(temptr->name); + free(temptr); + return 1; + } + if (np->next == NULL) { + np->next = temptr; + temptr->next = NULL; + strcpy(temptr->name,name); + return 0; + } + } + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: hash_fun + * + * Purpose: to get the hash value based on the key + * + * Return: No. of the hashtable + * + * In : name: object name + size: the hashtable size. + + *------------------------------------------------------------------------- + */ +int hash_fun(char *name,int size) { + +int hashval; + + for (hashval = 0;*name !='\0';) + hashval += *name++; + return(hashval%size); + +} + +/*------------------------------------------------------------------------- + * Function: freenametable + * + * Purpose: free the memory of hash table + * + * Return: 0 + * + * In : + SIZE: the hashtable SIZE. + nametab: hash table of the name + + *------------------------------------------------------------------------- + */ +int freenametable(int SIZE,struct name_table *nametab) { + + struct name_table *np,*temptr,*temptr1; + int i; + + if(nametab == NULL) return 0; + /* we first free the additional linked items of the hashtable, + and then free the whole hash table. */ + for (i = 0;i < SIZE; i++) { + np = nametab+i; + temptr1 = np->next; + while(temptr1 != NULL) { + temptr = temptr1; + temptr1 = temptr1->next; + free(temptr->name); + free(temptr); + } + if(np->name !=NULL) free(np->name); + } + free(nametab); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: freetable + * + * Purpose: free the memory of hash table + * + * Return: 0 + * + * In : + SIZE: the hashtable SIZE. + nametab: hash table + + *------------------------------------------------------------------------- + */ +int freetable(int SIZE,struct table *hashtab) { + + struct table *np,*temptr,*temptr1; + int i; + if(hashtab == NULL) return 0; + + /* we first free the additional linked items of the hashtable, + and then free the whole hash table. */ + for (i =0;i < SIZE; i++) { + np = hashtab+i; + temptr1 = np->next; + while(temptr1 != NULL) { + temptr = temptr1; + temptr1 = temptr1->next; + free(temptr->name); + free(temptr); + } + if(np->name != NULL) free(np->name); + } + + free(hashtab); + return 0; +} + +/*------------------------------------------------------------------------- + * Function: mkstr + * + * Purpose: make hdf5 string type + * + * Return: type + * + * In : + size: String Size + H5T_str_t: pad + + *------------------------------------------------------------------------- + */ + +hid_t mkstr(int size, H5T_str_t pad) { + + hid_t type; + + if((type=H5Tcopy(H5T_C_S1))<0) return -1; + if((H5Tset_size(type,(size_t)size))<0) return -1; + if((H5Tset_strpad(type,pad))<0) return -1; + + return type; +} + +/*------------------------------------------------------------------------- + * Function: h4_transnumattr + * + * Purpose: translate reference number into hdf5 attribute + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + h5g: hdf5 group id + refname: reference name + group_ref: reference number + + *------------------------------------------------------------------------- + */ +int h4_transnumattr(hid_t h5g,const char *refname,uint16 group_ref) { + + hid_t h5memtype=(-1); + hid_t h5a_id; + hid_t h5a_sid; + herr_t ret; + + h5a_sid = H5Screate(H5S_SCALAR); + + if (h5a_sid < 0) { + fprintf(stderr,"failed to create attribute space for HDF4_REF_NUM. \n"); + return FAIL; + } + + h5a_id = H5Acreate(h5g,refname,H5T_STD_U16BE,h5a_sid,H5P_DEFAULT); + + if(h5a_id <0) { + fprintf(stderr,"failed to obtain attribute id for HDF4_REF_NUM. \n"); + H5Sclose(h5a_sid); + return FAIL; + } + + if(H5Tget_size(H5T_NATIVE_CHAR)== sizeof(uint16)) + h5memtype = H5T_NATIVE_UCHAR; + else if(H5Tget_size(H5T_NATIVE_SHORT)== sizeof(uint16)) + h5memtype = H5T_NATIVE_USHORT; + else if(H5Tget_size(H5T_NATIVE_INT) == sizeof(uint16)) + h5memtype = H5T_NATIVE_UINT; + else if(H5Tget_size(H5T_NATIVE_LONG)== sizeof(uint16)) + h5memtype = H5T_NATIVE_ULONG; + + ret = H5Awrite(h5a_id,h5memtype,(void *)&group_ref); + + if(ret <0) { + printf("failed to obtain attribute.\n "); + H5Sclose(h5a_sid); + H5Aclose(h5a_id); + return FAIL; + } + + ret = H5Sclose(h5a_sid); + ret = H5Aclose(h5a_id); + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: h4_transpredattrs + * + * Purpose: translate predefined attributes into hdf5 attribute + * predefined attributes include HDF4 OBJECT TYPE, + HDF4 OBJECT NAME, HDF4 CLASS etc. They are all in + H5T_STRING format. + + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + h5g: group id + attrname: attribute name + data: attribute data + + *------------------------------------------------------------------------- + */ +int h4_transpredattrs(hid_t h5g,const char *attrname,char*data){ + + hsize_t h5str_size; + hid_t h5a_id; + hid_t h5a_sid; + hid_t h5str_type; + herr_t ret; + + if(data == NULL) { + printf("attribute data is not available.\n"); + return FAIL; + } + + h5str_size = strlen(data); + + if ((h5str_type = mkstr(h5str_size,H5T_STR_SPACEPAD))<0) { + printf("error in making string for predefined ATTR. \n"); + return FAIL; + } + + h5a_sid = H5Screate(H5S_SCALAR); + + if (h5a_sid < 0) { + printf("failed to create attribute space for HDF4_OBJECT. \n"); + return FAIL; + } + + h5a_id = H5Acreate(h5g,attrname,h5str_type,h5a_sid,H5P_DEFAULT); + + if(h5a_id <0) { + fprintf(stderr,"failed to obtain attribute id for HDF4_OBJECT. \n"); + H5Sclose(h5a_sid); + return FAIL; + } + + ret = H5Awrite(h5a_id,h5str_type,(void *)data); + + if(ret <0) { + fprintf(stderr,"failed to obtain attribute.\n "); + H5Aclose(h5a_id); + H5Sclose(h5a_sid); + return FAIL; + } + ret = H5Sclose(h5a_sid); + ret = H5Aclose(h5a_id); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: vg_transattrs + * + * Purpose: translate predefined vgroup attributes into hdf5 attribute + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + h4vg: hdf4 vgroup id + h5g: hdf5 group id + + *------------------------------------------------------------------------- + */ + +int vg_transattrs(int32 h4vg,hid_t h5g) { + + /* define variables for hdf4. */ + char vgroup_name[VGNAMELENMAX]; + char vgroup_class[VGNAMELENMAX]; + char vgattr_name[MAX_NC_NAME]; + char obtype[MAX_NC_NAME]; + + int32 vgroup_cref; + int32 num_vgattr; + int32 count_vgattr; + int32 vg_atype; + int32 attr_size; + + size_t sh4_size; + size_t sh4_amemsize; + + /* define variables for hdf5. */ + hid_t sh5a_sid; + hid_t sh5a_id; + hid_t sh5_atype; + hid_t sh5_amemtype; + hid_t sh5str_type; + hid_t sh5str_memtype; + hsize_t sh5dims[MAX_VAR_DIMS]; + void* vg_adata; + herr_t sret; + int i; + + num_vgattr = Vnattrs(h4vg); + + for (i = 0;i 0) freetable(estnum_vg,vg_hashtab); + if(estnum_vd > 0) freetable(estnum_vd,vd_hashtab); + + if(num_sds > 0) { + freetable(2*num_sds,sds_hashtab); + freenametable(DIM_HASHSIZE,dim_hashtab); + } + + if(num_images > 0) { + freetable(2*num_images,gr_hashtab); + freetable(PAL_HASHSIZE,pal_hashtab); + } + + if(num_objects > 0) freenametable(num_objects,name_hashtab); + +} + +/*------------------------------------------------------------------------- + * Function: correct_name + * + * Purpose: modify the hdf4 object name when the name contains '/'. Change + this character into '_'. + + * + * Return: the corrected name + * + * In : old name + + + *------------------------------------------------------------------------- + */ +char *correct_name(char* oldname){ + + char * cptr; + char * newname; + + if(oldname == NULL) { + printf("inputting name is wrong.\n"); + return NULL; + } + + newname = malloc(strlen(oldname)+1); + h4toh5_ZeroMemory(newname,strlen(oldname)+1); + newname = strncpy(newname, oldname, strlen(oldname)); + + while(strchr(newname,ORI_SLASH)!= NULL){ + cptr = strchr(newname,ORI_SLASH); + *cptr = CHA_SLASH; + } + + return newname; +} + + + + + + + + + + + + + + + + diff --git a/tools/h4toh5/h4toh5util.h b/tools/h4toh5/h4toh5util.h new file mode 100644 index 0000000..7e3def7 --- /dev/null +++ b/tools/h4toh5/h4toh5util.h @@ -0,0 +1,232 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +Including declarations of global variables,global hashtables,constant +and utility subroutines of h4toh5util.c + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + + +#ifndef UTILITY_H +#define UTILITY_H +#include "hdf5.h" +#include "hdf.h" + +/**********************************************/ +/*************** section I *******************/ +/*This section of the file describes reserved +name and global parameters used in h4-h5 +converter.*/ +/*********************************************/ + +/* 0. if "/" is found in hdf4 object name, we will use another + character "_" to replace it, since "/" is a reserved symbol for hdf5. */ + +#define ORI_SLASH '/' +#define CHA_SLASH '_' + +/* 1. character string used for default attribute name. */ +#define ATTR "ATTR" + +/* 2. Predefined HDF5 Attribute name for HDF4 file */ + +#define HDF4_OBJECT_NAME "HDF4_OBJECT_NAME" +#define HDF4_OBJECT_TYPE "HDF4_OBJECT_TYPE" +#define HDF4_REF_NUM "HDF4_REF_NUM" +#define HDF4_VGROUP_CLASS "HDF4_VGROUP_CLASS" +#define HDF4_IMAGE_CLASS "CLASS" +#define HDF4_IMAGE_SUBCLASS "IMAGE_SUBCLASS" +#define HDF4_PALETTE_CLASS "CLASS" +#define HDF4_PALETTE_TYPE "PAL_TYPE" +#define PAL_TYPE "STANDARD8" +#define PAL_COLORMODEL "PAL_COLORMODEL" +#define RGB "RGB" +/* 3. reserved name for HDF5 object name when meeting with name clashing. */ + +#define HDF4_VGROUP "HDF4_VGROUP" +#define HDF4_PALETTE "HDF4_PALETTE" +#define HDF4_SDS "HDF4_SDS" +#define HDF4_VDATA "HDF4_VDATA" +#define HDF4_IMAGE "HDF4_IMAGE" +#define HDF4_DIMSCALE "HDF4_DIMSCALE" + +/* 4. global palette and dimension_list name. */ +#define HDF4_IMAGE_PALETTE "HDF4_IMAGE_PALETTE" +#define HDF4_DIMENSION_LIST "HDF4_DIMENSION_LIST" +#define PALETTE "PALETTE" + +#define DIMSCALE "DIMSCALE" + +/* 5. define affix GLO for sds and image file attributes. these file attributes + will be put under root group. */ +#define GLOSDS "GLOSDS" +#define GLOIMAGE "GLOIMAGE" + +/* 6. define HDF object label.*/ +#define SDSLABEL "SDS" +#define VDATALABEL "Vdata" +#define VGROUPLABEL "Vgroup" +#define GRLABEL "GR" +#define RAST8LABEL "raster8" +#define RAST24LABEL "raster24" +#define PALABEL "palette" + +/* 7. define "IMAGE" CLASS required by image spec. */ +#define IM_CLASS "IMAGE" + +/* 8. reserved group name for HDF4 dimensional scale and palette. */ +#define HDF4_DIMG "/HDF4_DIMGROUP" +#define HDF4_PALG "/HDF4_PALGROUP" + +/* 9. reserved name for hdf4 file label,file description, object label, + object description. */ +#define HDF4_FILE_LABEL "HDF4_FILE_LABEL" +#define HDF4_FILE_DESC "HDF4_FILE_DESCRIPTION" +#define HDF4_OBJECT_LABEL "HDF4_OBJECT_LABEL" +#define HDF4_OBJECT_DESC "HDF4_OBJECT_DESCRIPTION" +#define HDF4_SDS_LABEL "HDF4_SDS_LABEL" +#define HDF4_SDS_DESC "HDF4_SDS_DESC" +#define HDF4_IMAGE_LABEL "HDF4_IMAGE_LABEL" +#define HDF4_IMAGE_DESC "HDF4_IMAGE_DESC" +#define HDF4_VDATA_LABEL "HDF4_VDATA_LABEL" +#define HDF4_VDATA_DESC "HDF4_VDATA_DESC" +#define HDF4_VGROUP_LABEL "HDF4_VGROUP_LABEL" +#define HDF4_VGROUP_DESC "HDF4_VGROUP_DESC" +#define HDF4_PAL_LABEL "HDF4_PAL_LABEL" +#define HDF4_PAL_DESC "HDF4_PAL_DESC" +#define HDF4_IMAGE_INDEXED "HDF4_IMAGE_INDEXED" + +/*10. palette and dimensional scale hash size and the + maximum length of object reference number in string format. + global variables of vgroup, vdata, sds, image and total number of + the object, number of global sds attributes and GR attributes.*/ + +#define PAL_HASHSIZE 64 +#define DIM_HASHSIZE 64 +#define VG_DEFHASHSIZE 64 +#define VD_DEFHASHSIZE 64 +#define MAXREF_LENGTH 5 +/*considering the string size of HDF4_DIMGROUP. we add this into 276.*/ +#define MAX_DIM_NAME 276 +#define MAX_PAL_NAME 32 +/*11. adding a specified vdata class name to deal with the situation when +independent vdata is hdf chunking table _HDF_CHK_TBL_CLASS, if it becomes +public constant for hdf lib, this constant can be released.*/ +#define _HDF_CHK_TBL_CLASS "_HDF_CHK_TBL_" + +extern int32 estnum_vg; +extern int32 estnum_vd; +extern int32 num_sds; +extern int32 num_images; +extern int num_objects; +extern int32 num_glsdsattrs; +extern int32 num_glgrattrs; + +/**********************************************/ +/*************** section II *******************/ +/*This section describes hash tables and their + functions used in h4-h5 converter.*/ +/*********************************************/ +/*define two kinds of hashtables. + 1. struct table uses object reference as the key to handle whether this + object is visited or not. + 2. struct name_table uses object name as the key to handle name clashings and + dimensional scale dataset. +*/ + +struct table { + int ref; + struct table *next; + char *name; +}; + +struct name_table { + char *name; + struct name_table *next; +}; + +extern struct table* sds_hashtab; +extern struct table* gr_hashtab; +extern struct table* vg_hashtab; +extern struct table* vd_hashtab; +extern struct table* pal_hashtab; +extern struct name_table* name_hashtab; +extern struct name_table* dim_hashtab; + +/* routine for zeroing out the memory. */ +void h4toh5_ZeroMemory(void*s,size_t n); + +/* look-up table, object reference is the key.*/ +int lookup(int,int,struct table*); + +/*look-up table, key is name. */ +int hash_fun(char*name,int size); +int lookup_name(char*, int,struct name_table*); + +/* routines that initialize the tables and name tables.*/ +int init_tab(int,struct table*); +int init_nametab(int,struct name_table*); + +/* get name and set name for table. */ +char* get_name(int,int,struct table *,int*); +int set_name(int,int,struct table *,char*); + +/* free table routines. */ +int freetable(int,struct table *); +int freenametable(int, struct name_table*); +void freehashmemory(void); + +/**********************************************/ +/*************** section III *******************/ +/*This section describes other common routines and their + functions used in h4-h5 converter.*/ +/*********************************************/ + +/* this routine defines the conversion of data type from h4 to h5. */ +herr_t h4type_to_h5type(const int32 h4type, hid_t* h5memtype, + size_t* h4memsize, size_t* h4size, hid_t *h5type); + +/* routines for translating predefined hdf4 attributes into hdf5 attributes*/ +int h4_transpredattrs(hid_t ,const char *,char*data); +int h4_transnumattr(hid_t h5g,const char *,uint16 group_ref); +int vg_transattrs(int32,hid_t); + +/*string and int conversion routines.*/ +hid_t mkstr(int size, H5T_str_t pad); +herr_t h5string_to_int(const int32, hid_t*,const size_t,hid_t* ); +int conv_int_str(uint16, char*); + +/* these routines were utility functions for other routines at h4toh5util.c */ +char* trans_obj_name(int32,int32); +char* get_obj_aboname(char*,char*,char*,const char*); +char* make_objname_no(char*,char*,const char*); +char* make_objname_yes(char*,char*); +char* correct_name(char*); + +#endif + + + + diff --git a/tools/h4toh5/h4toh5vdata.c b/tools/h4toh5/h4toh5vdata.c new file mode 100644 index 0000000..55a8bf9 --- /dev/null +++ b/tools/h4toh5/h4toh5vdata.c @@ -0,0 +1,831 @@ +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +Converting an hdf4 independent vdata object into an hdf5 dataset of compound dataset. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + +#include "h4toh5main.h" +#include + +/*------------------------------------------------------------------------- + * Function: Vdata_h4_to_h5 + * + * Purpose: translate Vdata object into hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + vdata_id: RI identifier + group_id: hdf5 group id + Out: + + Modification: + *------------------------------------------------------------------------- + */ + +int Vdata_h4_to_h5(int32 file_id,int32 vdata_id, hid_t group_id) { + + /* define variables for hdf4. */ + + int32 istat; + int32 n_records; + + int32 vdata_ref; + int32 vdata_tag; + + int32 interlace_mode; + + int32 vdata_size; + int32 vdatamem_size; + + int32 field_index; + int32 fieldorder; + int32 fieldtype; + + int i; + int32 nfields; + int num_vd_attrs; + int num_vd_field_attrs; + + VOIDP vd_data; + + char vdlabel[10]; + char vdata_name[MAX_NC_NAME]; + char fieldname[MAX_NC_NAME]; + char vdata_class[VSNAMELENMAX]; + char field_name_list[VSFIELDMAX*FIELDNAMELENMAX]; + + /* define varibles for hdf5. */ + + hid_t h5d_sid; + hid_t h5dset; + + hid_t h5_ctype; + hid_t h5_cmemtype; + + hid_t* h5memtype = NULL; + hid_t* h5type = NULL; + + size_t* h4memsize = NULL; + size_t* h4size = NULL; + hsize_t h5_vddims[1]; + char* h5cvdata_name; + + int check_vdname; + + /* Zeroing out memory for vdlabel,vdata_class,vdata_name */ + + h4toh5_ZeroMemory(vdata_name,MAX_NC_NAME); + h4toh5_ZeroMemory(fieldname,MAX_NC_NAME); + h4toh5_ZeroMemory(vdata_class,VSNAMELENMAX); + h4toh5_ZeroMemory(field_name_list,VSFIELDMAX*FIELDNAMELENMAX); + h4toh5_ZeroMemory(vdlabel,10); + + /* get absolute path of vdata name. */ + + vdata_ref = VSQueryref(vdata_id); + if (vdata_ref == FAIL) { + printf("error in getting reference number. \n"); + return FAIL; + } + + vdata_tag = VSQuerytag(vdata_id); + if (vdata_tag == FAIL) { + printf("error in getting object tag number. \n"); + return FAIL; + } + + /* get the class name */ + + if(VSgetclass(vdata_id,vdata_class) == FAIL) { + printf("error in obtaining class name. \n"); + return FAIL; + } + + /* get number of record,field_name,Size of a record and + Name of the vdata*/ + + if(VSQueryvsize(vdata_id,&vdata_size)==FAIL) { + printf("error in getting size of vdata. \n"); + return FAIL; + } + + if(vdata_size == 0) {/* empty vdata set. */ + return SUCCEED; + } + + /* obtain number of records, field name list, vdata name. */ + if(VSinquire(vdata_id,&n_records,&interlace_mode, + field_name_list,&vdata_size,vdata_name) == FAIL) { + printf("error in inquiring vdata. \n"); + return FAIL; + } + + vdatamem_size = 0; + vdata_size = 0; + nfields = VFnfields(vdata_id); + + if (nfields == FAIL) { + printf("error in obtaining number of vdata fields. \n"); + return FAIL; + } + + assert(nfields>0); + h5memtype = calloc((size_t)nfields,sizeof(hid_t)); + h5type = calloc((size_t)nfields,sizeof(hid_t)); + h4memsize = calloc((size_t)nfields,sizeof(size_t)); + h4size = calloc((size_t)nfields,sizeof(size_t)); + + for (i=0;i=0(vdata field).\n"); + return FAIL; + } + + for (i = 0;i < snum_vdattrs; i++) { + + /* if the field_index is 0, no field attribute exists, only + VDATA attributes are converted.*/ + + if (VSattrinfo(vdata_id,field_index,i,svdattr_name,&svd_atype, + &count_svdadata,NULL)== FAIL){ + printf("unable to obtain attribute information. \n"); + return FAIL; + } + + if(svdattr_name[0] == '\0') { + svdrepattr_name = trans_obj_name(DFTAG_VG,i); + strcpy(svdattr_name,svdrepattr_name); + free(svdrepattr_name); + } + + if (field_index == -1); + + else if (field_index != -1 && attr_name != NULL) { + + strcat(svdattr_name,":"); + strcat(svdattr_name,attr_name); + } + + else { + + strcat(svdattr_name,":"); + strcat(svdattr_name,"HDF4_VDATA_ATTR_"); + if(conv_int_str(field_index,refstr)==FAIL) { + printf("error in converting vdata field index to string.\n"); + return FAIL; + } + strcat(svdattr_name,refstr); + + } + + /* converting attribute data type into the corresponding hdf5 data type */ + + if(h4type_to_h5type(svd_atype,&sh5_amemtype,&sh4_amemsize, + &sh4_asize,&sh5_atype)==FAIL){ + printf("fail to translate vdata attribute datatype from H4 to H5.\n"); + return FAIL; + } + + svd_adata = malloc(sh4_amemsize * count_svdadata); + + if(svd_adata == NULL) { + printf("fail to allocate memory for vdata attribute data.\n"); + return FAIL; + } + + if(VSgetattr(vdata_id,field_index,i,(VOIDP)svd_adata)==FAIL){ + printf("error in getting attributes of vdata. \n"); + free(svd_adata); + return FAIL; + } + + /* now do attribute-transferring: + 1. deal with string data type + 2. set attribute space + 3. get attribute name */ + + if (sh5_atype == H5T_STRING) { + + if ((sh5str_type = mkstr(count_svdadata, + H5T_STR_SPACEPAD))<0) { + printf("error in making string for vdata attribute. \n"); + free(svd_adata); + return FAIL; + } + + if ((sh5str_memtype = mkstr(count_svdadata*sh4_amemsize, + H5T_STR_SPACEPAD))<0) { + printf("error in making memory string for vdata attribute. \n"); + free(svd_adata); + return FAIL; + } + + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create attribute space for "); + printf("HDF4_OBJECT_TYPE VDATA. \n"); + free(svd_adata); + return FAIL; + } + + + sh5a_id = H5Acreate(h5dset,svdattr_name,sh5str_type, + sh5a_sid,H5P_DEFAULT); + + if (sh5a_id <0) { + printf("failed to obtain attribute id for"); + printf(" HDF4_OBJECT_TYPE VDATA. \n"); + H5Sclose(sh5a_sid); + free(svd_adata); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)svd_adata); + + if (sret <0) { + printf("fail to write vdata attr into hdf5 dataset attr\n "); + H5Sclose(sh5a_sid); + H5Aclose(sh5a_id); + free(svd_adata); + return FAIL; + } + + free(svd_adata); + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + + else { + + if(count_svdadata == 1) { + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create scalar space id for hdf5 attribute "); + printf("of dataset converted from attribute of VDATA.\n"); + free(svd_adata); + return FAIL; + } + } + else { + sh5dims[0] = count_svdadata; + sh5a_sid = H5Screate_simple(1,sh5dims,NULL); + + if (sh5a_sid < 0) { + printf("failed to create simple space id for hdf5 attribute "); + printf("of dataset converted from attribute of VDATA.\n"); + free(svd_adata); + return FAIL; + } + } + + sh5a_id = H5Acreate(h5dset,svdattr_name,sh5_atype, + sh5a_sid,H5P_DEFAULT); + + if(sh5a_id <0) { + printf("failed to create attribute id for hdf5 attribute "); + printf("of dataset converted from attribute of VDATA.\n"); + H5Sclose(sh5a_sid); + free(svd_adata); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)svd_adata); + + if(sret <0) { + printf("failed to write attribute data for hdf5 attribute "); + printf("of dataset converted from attribute of VDATA.\n"); + H5Sclose(sh5a_sid); + H5Aclose(sh5a_id); + free(svd_adata); + return FAIL; + } + + sret = H5Aclose(sh5a_id); + sret = H5Sclose(sh5a_sid); + free(svd_adata); + } + } + return SUCCEED; +} +/*------------------------------------------------------------------------- + * Function: gen_h5comptype + * + * Purpose: generate hdf5 compound data type + + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + vdata_id: vdata identifier + nfields: number of fields + sh4size: pointer to datatype size in memory + sh4memsize: pointer to datatype size in memory + sh5type: pointer to hdf5 datatype + sh5memtype: pointer to actual hdf5 datatype in memory + h5_ctype: hdf5 compound datatype + h5_cmemtype: hdf5 compound datatype in memory + Out: + Modifications: + + *------------------------------------------------------------------------- + */ + +int gen_h5comptype(int32 vdata_id,int32 nfields, + size_t* sh4size,size_t* sh4memsize, + hid_t* sh5type,hid_t* sh5memtype, + hid_t h5_ctype,hid_t h5_cmemtype) { + + char* fieldname; + int32 fieldorder; + size_t fil_offset; + size_t mem_offset; + hsize_t fielddim[1]; + hid_t h5str_type; + int check_ifstr;/* flag to check if the h5 type is string.*/ + int i; + + + check_ifstr = 0; + fil_offset = 0; + mem_offset = 0; + + + for (i =0;i< nfields;i++) { + + fieldname = NULL; + fieldorder = VFfieldorder(vdata_id,i); + + if(fieldorder == FAIL){ + printf("error in obtaining fieldorder.\n"); + return FAIL; + } + + fieldname = VFfieldname(vdata_id,i); + if(fieldname == NULL){ + printf("fail to obtain Vdata field name. \n"); + return FAIL; + } + + + /* when vdata is a character array, we will write the whole + array as one hdf5 type string. */ + + if(sh5type[i] == H5T_STRING) { + + if ((h5str_type = mkstr(sh4size[i]*fieldorder,H5T_STR_SPACEPAD))<0) { + printf("error in making string of hdf5 string. \n"); + return FAIL; + } + sh5type[i] = h5str_type; + check_ifstr = 1; + } + + if (sh5memtype[i] == H5T_STRING) { + + if((h5str_type = mkstr(sh4memsize[i]*fieldorder,H5T_STR_SPACEPAD))<0){ + printf("error in making string for VDATA in memory. \n"); + return FAIL; + } + sh5memtype[i] = h5str_type; + + } + + fielddim[0] = fieldorder; + + /* if field type is an array, use H5Tinsert_array. + When the data type is H5T_STRING, + we will treat the the vdata as a HDF5 scalar type.*/ + + if (fielddim[0] == 1 || check_ifstr == 1) { + + if(H5Tinsert(h5_ctype,fieldname,fil_offset,sh5type[i])<0) { + printf("error inserting hdf5 compound datatype while "); + printf("converting vdata.\n"); + return FAIL; + } + + if(H5Tinsert(h5_cmemtype,fieldname,mem_offset,sh5memtype[i])<0){ + printf("error inserting hdf5 compound datatype of memory"); + printf(" while converting vdata.\n"); + return FAIL; + } + } + + else { + hid_t arr_type; /* Array datatype for inserting fields */ + + /* Create array datatype */ + if((arr_type=H5Tarray_create(sh5type[i],1,fielddim,NULL))<0) { + printf("error creating array datatype.\n"); + return FAIL; + } + + if(H5Tinsert(h5_ctype,fieldname,fil_offset,arr_type)<0) { + printf("error inserting array into hdf5 compound datatype. \n"); + return FAIL; + } + + /* Close array datatype */ + if(H5Tclose(arr_type)<0) { + printf("error closing array datatype.\n"); + return FAIL; + } + + /* Create array datatype */ + if((arr_type=H5Tarray_create(sh5memtype[i],1,fielddim,NULL))<0) { + printf("error creating array datatype.\n"); + return FAIL; + } + + if(H5Tinsert(h5_cmemtype,fieldname,mem_offset,arr_type)<0) { + printf("error inserting array into hdf5 compound datatype for memory. \n"); + return FAIL; + } + + /* Close array datatype */ + if(H5Tclose(arr_type)<0) { + printf("error closing array datatype.\n"); + return FAIL; + } + + + } + + if( check_ifstr == 1) { + fil_offset = fil_offset + sh4size[i]*fieldorder; + mem_offset = mem_offset + sh4memsize[i]*fieldorder; + check_ifstr = 0; + } + else { + + fil_offset = fil_offset + sh4size[i]*fieldorder; + mem_offset = mem_offset + sh4memsize[i]*fieldorder; + } + + } + + return SUCCEED; +} + + + + + + + + + + + + + + diff --git a/tools/h4toh5/h4toh5vgroup.c b/tools/h4toh5/h4toh5vgroup.c new file mode 100644 index 0000000..92a6735 --- /dev/null +++ b/tools/h4toh5/h4toh5vgroup.c @@ -0,0 +1,812 @@ + +/*------------------------------------------------------------------------- + * + * Copyright (C) 2000 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + */ + +/****************************************************************************** + + Description: + +1. converter + +See HDF4 to HDF5 mapping specification at +(http://hdf.ncsa.uiuc.edu/HDF5/papers/h4toh5) for the default mapping +from HDF4 object to HDF5 object. + +The whole converter includes 10 files, h4toh5util.h, h4toh5main.h, h4toh5util.c, h4toh5main.c, h4toh5sds.c, h4toh5image.c,h4toh5vdata.c,h4toh5vgroup.c,h4toh5pal.c and h4toh5anno.c. + +2. this file + +converting an hdf4 vgroup object into a hdf5 group. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + + +#include "h4toh5main.h" + + +/*------------------------------------------------------------------------- + * Function: Vgroup_h4_to_h5 + * + * Purpose: translate different Vgroup objects: vgroup,vdata,sds,image + into hdf5 datasets and recursively call the routine + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf4 file identifier + vgroup_id: hdf4 vgroup id + sd_id: sd interface id + h5_group: hdf5 group id + h5_dimgroup: hdf5 dimensional scale group id + h5_palgroup: hdf5 palette group id + Out: + + Modification: + *------------------------------------------------------------------------- + */ + + +int Vgroup_h4_to_h5(int32 file_id,int32 vgroup_id,int32 sd_id,hid_t h5_group,hid_t h5_dimgroup,hid_t h5_palgroup) + +{ + + int32 vgroup_tag; + int32 vgroup_ref; + int32 obj_tag; + int32 obj_ref; + int32 num_gobjects; + int i; + + char refstr[MAXREF_LENGTH]; + char vgroup_class[VGNAMELENMAX]; + char vgroup_name[VGNAMELENMAX]; + + char* h5pgroup_name; + + int check_vgname; + hid_t h5_pgroup; + + /*zeroing out memory for vgroup_class and vgroup_name */ + h4toh5_ZeroMemory(vgroup_class,VGNAMELENMAX); + h4toh5_ZeroMemory(vgroup_name,VGNAMELENMAX); + + vgroup_tag = VQuerytag(vgroup_id); + if(vgroup_tag == FAIL) { + printf("error in obtaining vgroup tag.\n"); + return FAIL; + } + + vgroup_ref = VQueryref(vgroup_id); + if(vgroup_ref == FAIL) { + printf("error in obtaining vgroup reference.\n"); + return FAIL; + } + + if(Vgetname(vgroup_id,vgroup_name) == FAIL) { + printf("error in obtaining vgroup name.\n"); + return FAIL; + } + + if(Vgetclass(vgroup_id,vgroup_class) == FAIL) { + printf("error in obtaining vgroup class name. \n"); + return FAIL; + } + + /*** ignore reserved HDF group ***/ + + if(vgroup_class != NULL) { + if(strcmp(vgroup_class,_HDF_ATTRIBUTE)==0) return SUCCEED; + if(strcmp(vgroup_class,_HDF_VARIABLE)==0) return SUCCEED; + if(strcmp(vgroup_class,_HDF_DIMENSION)==0) return SUCCEED; + if(strcmp(vgroup_class,_HDF_UDIMENSION)==0) return SUCCEED; + if(strcmp(vgroup_class,_HDF_CDF)==0) return SUCCEED; + if(strcmp(vgroup_class,GR_NAME)==0) return SUCCEED; + if(strcmp(vgroup_class,RI_NAME)==0) return SUCCEED; + } + + if(vgroup_name != NULL) + if(strcmp(vgroup_name,GR_NAME)==0) return SUCCEED; + + h5pgroup_name = get_name(vgroup_ref,estnum_vg,vg_hashtab,&check_vgname); + + if(h5pgroup_name == NULL && check_vgname == 0 ) { + printf("error,cannot find group\n"); + return FAIL; + } + + if(h5pgroup_name == NULL && check_vgname ==-1 ) { + printf("error,group name is not defined.\n"); + return FAIL; + } + + /* create a hdf5 group under h5_group.*/ + + h5_pgroup = H5Gcreate(h5_group,h5pgroup_name,0); + + if(h5_pgroup < 0) { + printf("error in creating group. \n"); + free(h5pgroup_name); + return FAIL; + } + + /* vgroup attributes into corresponding hdf5 group attributes.*/ + if(vg_transattrs(vgroup_id,h5_pgroup)==FAIL) { + printf("error in translating vgroup attributes into hdf5 group attr.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + + num_gobjects = Vntagrefs(vgroup_id); + + if(num_gobjects == FAIL) { + printf("error in obtaining number of objects in the vgroup. \n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + + if(Annoobj_h4_to_h5(file_id,vgroup_ref,vgroup_tag,h5_pgroup)==FAIL) { + printf("error in obtaining annotation of the vgroup.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + + for( i = 0;i $tmpfile +if test -s "$tmpfile"; then + : +else + echo " Could not run the '$H5DUMP' command. The test can still proceed" + echo " but it may fail if '$H5DUMP' is needed to verify the output." + echo " You can make sure '$H5DUMP' is among your shell PATH and run" + echo " the test again. You may also visit http://hdf.ncsa.uiuc.edu" + echo " or email hdfhelp@ncsa.uiuc.edu for more information." + H5DUMP=: +fi +$RM $tmpfile + +# The build (current) directory might be different than the source directory. +if test -z "$srcdir"; then + srcdir=. +fi + +mkdir ../testfiles >/dev/null 2>&1 + +SRCDIR="$srcdir/../testfiles" +OUTDIR="../testfiles/Results" + +test -d "$OUTDIR" || mkdir $OUTDIR + +nerrors=0 +verbose=yes + +# Print a line-line message left justified in a field of 70 characters +# beginning with the word "Testing". +TESTING() { + SPACES=" " + echo "Testing $* $SPACES" |cut -c1-70 |tr -d '\012' +} + +# Run a test and print PASS or *FAIL*. If a test fails then increment +# the `nerrors' global variable and (if $verbose is set) display the +# difference between the actual and the expected hdf4 files. The +# expected hdf5 files are in testfiles/Expected directory. +# The actual hdf5 file is not removed if $HDF5_NOCLEANUP is to a non-null +# value. +CONVERT() { + # Run h4toh5 convert. + TESTING $H4TOH5 $@ + + # + # Set up arguments to run the conversion test. + # The converter assumes all hdf4 files has the .hdf suffix as in the form + # of foo.hdf. It creates the corresponding hdf5 files with the .h5 suffix + # as in the form of foo.h5. One exception is that if exactly two file + # names are given, it treats the first argument as an hdf4 file and creates + # the corresponding hdf5 file with the name as the second argument, WITOUT + # any consideration of the suffix. (For this test script, in order to + # match the output hdf5 file with the expected hdf5 file, it expects the + # second file of the two-files tests has the .h5 suffix too.) + # + # If SRCDIR != OUTDIR, need to copy the input hdf4 files from the SRCDIR + # to the OUTDIR and transform the input file pathname because of the suffix + # convention mentioned above. This way, the hdf5 files are always created + # in the OUTDIR directory. + # + + INFILES="" + OUTFILES="" + MULTIRUN="" + + case "$1" in + -m) # multiple files conversion + MULTIRUN="-m" + shift + for f in $* + do + if test "$SRCDIR" != "$OUTDIR"; then + cp $SRCDIR/$f $OUTDIR/$f + fi + INFILES="$INFILES $f" + OUTFILES="$OUTFILES `basename $f .hdf`.h5" + shift + done + ;; + + *) # Single file conversion + case $# in + 1) if test "$SRCDIR" != "$OUTDIR"; then + cp $SRCDIR/$1 $OUTDIR/$1 + fi + INFILES="$1" + OUTFILES="`basename $1 .hdf`.h5" + ;; + + 2) # hdf4 file specified + if test "$SRCDIR" != "$OUTDIR"; then + cp $SRCDIR/$1 $OUTDIR/$1 + fi + INFILES="$1" + OUTFILES="$2" + ;; + + *) # Illegal + echo "Illegal arguments" + exit 1 + ;; + esac + ;; + esac + + # run the conversion and remove input files that have been copied over + ( + cd $OUTDIR + $H4TOH5_BIN $INFILES $OUTFILES 2>/dev/null + if test "$SRCDIR" != "$OUTDIR"; then + $RM $INFILES + fi + ) + + # Verify results + result="passed" + for f in $OUTFILES + do + if $CMP $SRCDIR/Expected/$f $OUTDIR/$f + then + : + else + # Use h5dump to dump the files and verify the output. + outfile=`basename $f .h5` + expect_out=$outfile.expect + actual_out=$outfile.actual + + (cd $SRCDIR/Expected + $H5DUMP $outfile.h5 ) > $expect_out + (cd $OUTDIR + $H5DUMP $outfile.h5 ) > $actual_out + + if [ "passed" = $result -a ! -s $actual_out ] ; then + echo "*FAILED*" + nerrors="`expr $nerrors + 1`" + result=failed + test yes = "$verbose" && + echo " H5DUMP failed to produce valid output" + elif $CMP $expect_out $actual_out; then + : + else + if test "passed" = $result; then + echo "*FAILED*" + nerrors="`expr $nerrors + 1`" + result=failed + fi + test yes = "$verbose" && + echo " Actual result (*.actual) differs from expected result (*.expect)" && + $DIFF $expect_out $actual_out |sed 's/^/ /' + fi + fi + + # Clean up output file + if test -z "$HDF5_NOCLEANUP"; then + $RM $expect_out $actual_out + $RM $OUTDIR/$f + fi + done + if test "passed" = "$result"; then + echo " PASSED" + fi +} + +############################################################################## +############################################################################## +### T H E T E S T S ### +############################################################################## +############################################################################## + +$RM $OUTDIR/*.hdf $OUTDIR/*.tmp + +# +# The HDF5 filenames are created based upon the HDF4 filenames +# without the extension. +# + +# test for converting H5 groups to H4 Vgroups. +#CONVERT vg.hdf + + +# +# The test for conversion are the same as above with the only difference +# being that the HDF5 filenames are given explicitly. +# + +$RM $OUTDIR/*.tmp +CONVERT anno_test.hdf anno_test.h5 +CONVERT gr_typ_test.hdf gr_typ_test.h5 +CONVERT grnameclash_test.hdf grnameclash_test.h5 +CONVERT image_attr_test.hdf image_attr_test.h5 +#CONVERT image_maxsize.hdf image_maxsize.h5 +CONVERT ras_24_test.hdf ras_24_test.h5 +CONVERT ras_8_test.hdf ras_8_test.h5 +CONVERT sds_attr_test.hdf sds_attr_test.h5 +CONVERT sds_dim_test.hdf sds_dim_test.h5 +CONVERT sds_typ_test.hdf sds_typ_test.h5 +CONVERT sdsnameclash_test.hdf sdsnameclash_test.h5 +CONVERT vdata_test.hdf vdata_test.h5 +CONVERT vdnameclash_test.hdf vdnameclash_test.h5 +CONVERT vg_hl_test.hdf vg_hl_test.h5 +CONVERT vg_loop_test.hdf vg_loop_test.h5 +CONVERT vgnameclash_test.hdf vgnameclash_test.h5 +CONVERT vg_all_test.hdf vg_all_test.h5 +# +# Again, the test for conversion are the same as the first set of test. +# Here, multiple conversion are done on HDF4 files at one time. +# + +$RM $OUTDIR/*.hdf $OUTDIR/*.tmp +#CONVERT -m vg.hdf + +if test $nerrors -eq 0 ; then + echo "All h4toh5 tests passed." +fi + +$RM -r $OUTDIR +exit $nerrors diff --git a/tools/h5dump/Dependencies b/tools/h5dump/Dependencies new file mode 100644 index 0000000..e69de29 diff --git a/tools/h5dump/Makefile.in b/tools/h5dump/Makefile.in new file mode 100644 index 0000000..6de1b7c --- /dev/null +++ b/tools/h5dump/Makefile.in @@ -0,0 +1,65 @@ +## HDF5 Library Makefile(.in) +## +## Copyright (C) 2001 National Center for Supercomputing Applications. +## All rights reserved. +## +## +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +SUBDIRS= +@COMMENCE@ + +## Add include directory to the C preprocessor flags, add -lh5tools and +## -lhdf5 to the list of libraries. +## +CPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src \ + -I$(top_srcdir)/tools/lib @CPPFLAGS@ + +## Test programs and scripts. +## +TEST_PROGS= +TEST_SCRIPTS=$(srcdir)/testh5dump.sh + +## These are our main targets: library and tools. +## +LIBTOOLS=../lib/libh5tools.la +LIBHDF5=$(top_builddir)/src/libhdf5.la + +PUB_PROGS=h5dump +PROGS=$(PUB_PROGS) $(TEST_PROGS) h5dumptst + +## Source and object files for the library; do not install +## +LIB_SRC= +LIB_OBJ=$(LIB_SRC:.c=.lo) +PUB_LIB= + +## Source and object files for programs... +## +PROG_SRC=h5dump.c h5dumptst.c +PROG_OBJ=$(PROG_SRC:.c=.lo) + +PRIVATE_HDR=h5dump.h + +## Source and object files for the tests +## +TEST_SRC= +TEST_OBJ=$(TEST_SRC:.c=.lo) + +## Programs have to be built before they can be tested! +## +check test _test: $(PROGS) + +## How to build the programs...They all depend on the hdf5 library and +## the tools library compiled in this directory. +## +$(PROGS): $(LIBTOOLS) $(LIBHDF5) + +h5dump: h5dump.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ h5dump.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +h5dumptst: h5dumptst.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ h5dumptst.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +@CONCLUDE@ diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c new file mode 100644 index 0000000..23c3bd2 --- /dev/null +++ b/tools/h5dump/h5dump.c @@ -0,0 +1,4680 @@ +/* + * Copyright (C) 1998-2001 National Center for Supercomputing Applications + * All rights reserved. + * + */ +#include +#include + +#include "h5dump.h" +#include "H5private.h" +#include "h5tools.h" + +/* module-scoped variables */ +static const char *progname = "h5dump"; + +static int d_status = EXIT_SUCCESS; +static int unamedtype = 0; /* shared data type with no name */ +static int prefix_len = 1024; +static table_t *group_table = NULL, *dset_table = NULL, *type_table = NULL; +static char *prefix; + +static const dump_header *dump_header_format; + +/* things to display or which are set via command line parameters */ +static int display_all = TRUE; +static int display_bb = FALSE; +static int display_oid = FALSE; +static int display_data = TRUE; +static int usingdasho = FALSE; + +/** + ** Added for XML ** + **/ + +/* fill_ref_path_table is called to inialize the object reference paths. */ +static herr_t fill_ref_path_table(hid_t, const char *, void UNUSED *); + +/* module-scoped variables for XML option */ +#define DEFAULT_DTD "http://hdf.ncsa.uiuc.edu/DTDs/HDF5-File.dtd" + +static int doxml = 0; +static const char *xml_dtd_uri = NULL; +static hid_t thefile = -1; +/** end XML **/ + +/* internal functions */ +static void dump_oid(hid_t oid); +static void print_enum(hid_t type); +static herr_t dump_all(hid_t group, const char *name, void *op_data); +static char *lookup_ref_path(hobj_ref_t *); +static void check_compression(hid_t); +static struct ref_path_table_entry_t *ref_path_table_lookup(const char *); + +/* external functions */ +extern int print_data(hid_t, hid_t, int); + +static h5dump_t dataformat = { + 0, /*raw */ + + "", /*fmt_raw */ + "%d", /*fmt_int */ + "%u", /*fmt_uint */ + "%d", /*fmt_schar */ + "%u", /*fmt_uchar */ + "%d", /*fmt_short */ + "%u", /*fmt_ushort */ + "%ld", /*fmt_long */ + "%lu", /*fmt_ulong */ + NULL, /*fmt_llong */ + NULL, /*fmt_ullong */ + "%g", /*fmt_double */ + "%g", /*fmt_float */ + + 0, /*ascii */ + 0, /*str_locale */ + 0, /*str_repeat */ + + "[ ", /*arr_pre */ + ", ", /*arr_sep */ + " ]", /*arr_suf */ + 1, /*arr_linebreak */ + + "", /*cmpd_name */ + ",\n", /*cmpd_sep */ + "{\n", /*cmpd_pre */ + "}", /*cmpd_suf */ + "\n", /*cmpd_end */ + + ",", /*vlen_sep */ + "(", /*vlen_pre */ + ")", /*vlen_suf */ + "", /*vlen_end */ + + "%s", /*elmt_fmt */ + ",", /*elmt_suf1 */ + " ", /*elmt_suf2 */ + + "", /*idx_n_fmt */ + "", /*idx_sep */ + "", /*idx_fmt */ + + 80, /*line_ncols *//*standard default columns */ + 0, /*line_per_line */ + "", /*line_pre */ + "%s", /*line_1st */ + "%s", /*line_cont */ + "", /*line_suf */ + "", /*line_sep */ + 1, /*line_multi_new */ + " ", /*line_indent */ + + 1, /*skip_first */ + + 1, /*obj_hidefileno */ + " %lu:%lu", /*obj_format */ + + 1, /*dset_hidefileno */ + "DATASET %lu:%lu ", /*dset_format */ + "%s", /*dset_blockformat_pre */ + "%s", /*dset_ptformat_pre */ + "%s", /*dset_ptformat */ +}; + +/** + ** Added for XML ** + **/ +/* + * Alternative formating for data dumped to XML + * In general, the numbers are the same, but separators + * except spaces are not used. + * + * Some of these are not used, as some kinds of data are + * dumped in completely new subroutines. + * + * Some of this formatting may yet need to change. + * + * This table only affects XML output. + */ +static h5dump_t xml_dataformat = { + 0, /*raw */ + + "", /*fmt_raw */ + "%d", /*fmt_int */ + "%u", /*fmt_uint */ + "%d", /*fmt_schar */ + "%u", /*fmt_uchar */ + "%d", /*fmt_short */ + "%u", /*fmt_ushort */ + "%ld", /*fmt_long */ + "%lu", /*fmt_ulong */ + NULL, /*fmt_llong */ + NULL, /*fmt_ullong */ + "%g", /*fmt_double */ + "%g", /*fmt_float */ + + 0, /*ascii */ + 0, /*str_locale */ + 0, /*str_repeat */ + + " ", /*arr_pre */ + " ", /*arr_sep */ + " ", /*arr_suf */ + 1, /*arr_linebreak */ + + "", /*cmpd_name */ + " ", /*cmpd_sep */ + "", /*cmpd_pre */ + "", /*cmpd_suf */ + "", /*cmpd_end */ + + " ", /*vlen_sep */ + " ", /*vlen_pre */ + " ", /*vlen_suf */ + "", /*vlen_end */ + + "%s", /*elmt_fmt */ + " ", /*elmt_suf1 */ + "", /*elmt_suf2 */ + + "", /*idx_n_fmt */ + "", /*idx_sep */ + "", /*idx_fmt */ + + 80, /*line_ncols *//*standard default columns */ + 0, /*line_per_line */ + "", /*line_pre */ + "%s", /*line_1st */ + "%s", /*line_cont */ + "", /*line_suf */ + "", /*line_sep */ + 1, /*line_multi_new */ + " ", /*line_indent */ + + 1, /*skip_first */ + + 1, /*obj_hidefileno */ + " %lu:%lu", /*obj_format */ + + 1, /*dset_hidefileno */ + "DATASET %lu:%lu ", /*dset_format */ + "%s", /*dset_blockformat_pre */ + "%s", /*dset_ptformat_pre */ + "%s", /*dset_ptformat */ +}; + +/** XML **/ + +static const dump_header standardformat = { + "standardformat", /*name */ + "HDF5", /*fileebgin */ + "", /*fileend */ + BOOT_BLOCK, /*bootblockbegin */ + "", /*bootblockend */ + GROUPNAME, /*groupbegin */ + "", /*groupend */ + DATASET, /*datasetbegin */ + "", /*datasetend */ + ATTRIBUTE, /*attributebegin */ + "", /*attributeend */ + DATATYPE, /*datatypebegin */ + "", /*datatypeend */ + DATASPACE, /*dataspacebegin */ + "", /*dataspaceend */ + DATA, /*databegin */ + "", /*dataend */ + SOFTLINK, /*softlinkbegin */ + "", /*softlinkend */ + + "{", /*fileblockbegin */ + "}", /*fileblockend */ + "{", /*bootblockblockbegin */ + "}", /*bootblockblockend */ + "{", /*groupblockbegin */ + "}", /*groupblockend */ + "{", /*datasetblockbegin */ + "}", /*datasetblockend */ + "{", /*attributeblockbegin */ + "}", /*attributeblockend */ + "", /*datatypeblockbegin */ + "", /*datatypeblockend */ + "", /*dataspaceblockbegin */ + "", /*dataspaceblockend */ + "{", /*datablockbegin */ + "}", /*datablockend */ + "{", /*softlinkblockbegin */ + "}", /*softlinkblockend */ + "{", /*strblockbegin */ + "}", /*strblockend */ + "{", /*enumblockbegin */ + "}", /*enumblockend */ + "{", /*structblockbegin */ + "}", /*structblockend */ + "{", /*vlenblockbegin */ + "}", /*vlenblockend */ + + "", /*dataspacedescriptionbegin */ + "", /*dataspacedescriptionend */ + "(", /*dataspacedimbegin */ + ")", /*dataspacedimend */ +}; + +/** + ** Added for XML ** + **/ +/* The 'header' formats for XML -- mostly null + * + * XML output has values embedded in the 'headers', so + * all the XML headers are done on a case by case basis. + */ +static const dump_header xmlformat = { + "xml", /*name */ + "", /*filebegin */ + "", /*fileend */ + "", /*bootblockbegin */ + "", /*bootblockend */ + "", /*groupbegin */ + "", /*groupend */ + "", /*datasetbegin */ + "", /*datasetend */ + "", /*attributebegin */ + "", /*attributeend */ + "", /*datatypeend */ + "", /*datatypeend */ + "", /*dataspacebegin */ + "", /*dataspaceend */ + "", /*databegin */ + "", /*dataend */ + "", /*softlinkbegin */ + "", /*softlinkend */ + + "", /*fileblockbegin */ + "", /*fileblockend */ + "", /*bootblockblockbegin */ + "", /*bootblockblockend */ + "", /*groupblockbegin */ + "", /*groupblockend */ + "", /*datasetblockbegin */ + "", /*datasetblockend */ + "", /*attributeblockbegin */ + "", /*attributeblockend */ + "", /*datatypeblockbegin */ + "", /*datatypeblockend */ + "", /*dataspaceblockbegin */ + "", /*dataspaceblockend */ + "", /*datablockbegin */ + "", /*datablockend */ + "", /*softlinkblockbegin */ + "", /*softlinkblockend */ + "", /*strblockbegin */ + "", /*strblockend */ + "", /*enumblockbegin */ + "", /*enumblockend */ + "", /*structblockbegin */ + "", /*structblockend */ + "", /*vlenblockbegin */ + "", /*vlenblockend */ + + "", /*dataspacedescriptionbegin */ + "", /*dataspacedescriptionend */ + "", /*dataspacedimbegin */ + "", /*dataspacedimend */ +}; + +/** XML **/ + +/** + ** Added for XML ** + **/ +/* internal functions used by XML option */ +static void xml_print_datatype(hid_t); +static void xml_print_enum(hid_t); +static int xml_print_refs(hid_t, int); +static int xml_print_strs(hid_t, int); +static hobj_ref_t *ref_path_table_put(hid_t, const char *); +static char *xml_escape_the_string(const char *, int); +static char *xml_escape_the_name(const char *); + +/** + ** Change for XML ** + ** + ** The 'dump_xxx' functions have two versions, standard and XML. + ** + ** They are called indirectly through the 'dump_function_table'. + ** e.g., dump_group(...) becomes dump_functions->dump_group(...); + ** + ** The standard functions are unchanged except for the way + ** they are called + **/ + +/* The dump functions of the dump_function_table */ + +/* standard format: no change */ +static void dump_group(hid_t, const char *); +static void dump_dataset(hid_t, const char *); +static void dump_data(hid_t, int); +static void dump_named_datatype(hid_t, const char *); +static void dump_dataspace(hid_t space); +static void dump_datatype(hid_t type); +static herr_t dump_attr(hid_t attr, const char *attr_name, + void UNUSED * op_data); + +/* XML format: same interface, alternative output */ + +static void xml_dump_group(hid_t, const char *); +static void xml_dump_dataset(hid_t ds, const char *dsname); +static void xml_dump_data(hid_t, int); +static void xml_dump_named_datatype(hid_t, const char *); +static void xml_dump_dataspace(hid_t space); +static void xml_dump_datatype(hid_t type); +static herr_t xml_dump_attr(hid_t attr, const char *attr_name, + void UNUSED * op_data); + +/** + ** Added for XML ** + ** + ** This is the global dispatch table for the dump functions. + **/ +/* the table of dump functions */ +typedef struct dump_functions_t { + void (*dump_group_function) (hid_t, const char *); + void (*dump_named_datatype_function) (hid_t, const char *); + void (*dump_dataset_function) (hid_t, const char *); + void (*dump_dataspace_function) (hid_t); + void (*dump_datatype_function) (hid_t); + herr_t (*dump_attribute_function) (hid_t, const char *, void *); + void (*dump_data_function) (hid_t, int); +} dump_functions; + +/* Standard DDL output */ +static const dump_functions ddl_function_table = { + dump_group, + dump_named_datatype, + dump_dataset, + dump_dataspace, + dump_datatype, + dump_attr, + dump_data +}; + +/* XML output */ +static const dump_functions xml_function_table = { + xml_dump_group, + xml_dump_named_datatype, + xml_dump_dataset, + xml_dump_dataspace, + xml_dump_datatype, + xml_dump_attr, + xml_dump_data +}; + +/* + * The global table is set to either ddl_function_table or + * xml_function_table in the initialization. + */ +static const dump_functions *dump_function_table; + +/* a structure to hold the subsetting particulars for a dataset */ +struct subset_t { + hsize_t *start; + hsize_t *stride; + hsize_t *count; + hsize_t *block; +}; + +/* a structure for handling the order command-line parameters come in */ +struct handler_t { + void (*func)(hid_t, char *, void *); + char *obj; + struct subset_t *subset_info; +}; + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +#if 0 + /* binary: not implemented yet */ +static const char *s_opts = "hbBHvVa:d:g:l:t:w:xD:o:s:T:c:k:"; +#else +static const char *s_opts = "hBHvVa:d:g:l:t:w:xD:o:s:T:c:k:"; +#endif /* 0 */ +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h' }, +#if 0 + /* binary: not implemented yet */ + { "binary", no_arg, 'b' }, + { "binar", no_arg, 'b' }, + { "bina", no_arg, 'b' }, + { "bin", no_arg, 'b' }, + { "bi", no_arg, 'b' }, +#endif /* 0 */ + { "boot-block", no_arg, 'B' }, + { "boot-bloc", no_arg, 'B' }, + { "boot-blo", no_arg, 'B' }, + { "boot-bl", no_arg, 'B' }, + { "boot-b", no_arg, 'B' }, + { "boot", no_arg, 'B' }, + { "boo", no_arg, 'B' }, + { "bo", no_arg, 'B' }, + { "header", no_arg, 'H' }, + { "heade", no_arg, 'H' }, + { "head", no_arg, 'H' }, + { "hea", no_arg, 'H' }, + { "object-ids", no_arg, 'i' }, + { "object-id", no_arg, 'i' }, + { "object-i", no_arg, 'i' }, + { "object", no_arg, 'i' }, + { "objec", no_arg, 'i' }, + { "obje", no_arg, 'i' }, + { "obj", no_arg, 'i' }, + { "ob", no_arg, 'i' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "ver", no_arg, 'V' }, + { "ve", no_arg, 'V' }, + { "attribute", require_arg, 'a' }, + { "attribut", require_arg, 'a' }, + { "attribu", require_arg, 'a' }, + { "attrib", require_arg, 'a' }, + { "attri", require_arg, 'a' }, + { "attr", require_arg, 'a' }, + { "att", require_arg, 'a' }, + { "at", require_arg, 'a' }, + { "block", require_arg, 'k' }, + { "bloc", require_arg, 'k' }, + { "blo", require_arg, 'k' }, + { "bl", require_arg, 'k' }, + { "count", require_arg, 'c' }, + { "coun", require_arg, 'c' }, + { "cou", require_arg, 'c' }, + { "co", require_arg, 'c' }, + { "dataset", require_arg, 'd' }, + { "datase", require_arg, 'd' }, + { "datas", require_arg, 'd' }, + { "datatype", require_arg, 't' }, + { "datatyp", require_arg, 't' }, + { "dataty", require_arg, 't' }, + { "datat", require_arg, 't' }, + { "group", require_arg, 'g' }, + { "grou", require_arg, 'g' }, + { "gro", require_arg, 'g' }, + { "gr", require_arg, 'g' }, + { "output", require_arg, 'o' }, + { "outpu", require_arg, 'o' }, + { "outp", require_arg, 'o' }, + { "out", require_arg, 'o' }, + { "ou", require_arg, 'o' }, + { "soft-link", require_arg, 'l' }, + { "soft-lin", require_arg, 'l' }, + { "soft-li", require_arg, 'l' }, + { "soft-l", require_arg, 'l' }, + { "soft", require_arg, 'l' }, + { "sof", require_arg, 'l' }, + { "so", require_arg, 'l' }, + { "start", require_arg, 's' }, + { "star", require_arg, 's' }, + { "sta", require_arg, 's' }, + { "stride", require_arg, 'T' }, + { "strid", require_arg, 'T' }, + { "stri", require_arg, 'T' }, + { "str", require_arg, 'T' }, + { "width", require_arg, 'w' }, + { "widt", require_arg, 'w' }, + { "wid", require_arg, 'w' }, + { "wi", require_arg, 'w' }, + { "xml", no_arg, 'x' }, + { "xm", no_arg, 'x' }, + { "xml-dtd", require_arg, 'D' }, + { "xml-dt", require_arg, 'D' }, + { "xml-d", require_arg, 'D' }, + { NULL, 0, '\0' } +}; + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message about dumper + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage(const char *prog) +{ + fflush(stdout); + fprintf(stdout, "\ +usage: %s [OPTIONS] file\n\ + OPTIONS\n\ + -h, --help Print a usage message and exit\n\ + -B, --bootblock Print the content of the boot block\n\ + -H, --header Print the header only; no data is displayed\n\ + -i, --object-ids Print the object ids\n\ + -V, --version Print version number and exit\n\ + -a P, --attribute=P Print the specified attribute\n\ + -d P, --dataset=P Print the specified dataset\n\ + -g P, --group=P Print the specified group and all members\n\ + -l P, --soft-link=P Print the value(s) of the specified soft link\n\ + -o F, --output=F Output raw data into file F\n\ + -t T, --datatype=T Print the specified named data type\n\ + -w N, --width=N Set the number of columns of output\n\ + -x, --xml Output in XML\n\ + -D U, --xml-dtd=U Use the DTD at U\n\ +\n\ + P - is the full path from the root group to the object.\n\ + T - is the name of the data type.\n\ + F - is a filename.\n\ + N - is an integer greater than 1.\n\ + U - is a URI reference (as defined in [IETF RFC 2396],\n\ + updated by [IETF RFC 2732])\n\ +\n\ + Example:\n\ +\n\ + Attribute foo of the group /bar_none in file quux.h5\n\ +\n\ + h5dump -a /bar_none/foo quux.h5\n\ +\n", prog); +} + +/*------------------------------------------------------------------------- + * Function: print_datatype + * + * Purpose: print the data type. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_datatype(hid_t type) +{ + char *fname; + hid_t nmembers, mtype, str_type; + int i, j, ndims, perm[H5DUMP_MAX_RANK]; + size_t size; + hsize_t dims[H5DUMP_MAX_RANK]; + H5T_str_t str_pad; + H5T_cset_t cset; + H5G_stat_t statbuf; + hid_t super; + + switch (H5Tget_class(type)) { + case H5T_INTEGER: + if (H5Tequal(type, H5T_STD_I8BE)) { + printf("H5T_STD_I8BE"); + } else if (H5Tequal(type, H5T_STD_I8LE)) { + printf("H5T_STD_I8LE"); + } else if (H5Tequal(type, H5T_STD_I16BE)) { + printf("H5T_STD_I16BE"); + } else if (H5Tequal(type, H5T_STD_I16LE)) { + printf("H5T_STD_I16LE"); + } else if (H5Tequal(type, H5T_STD_I32BE)) { + printf("H5T_STD_I32BE"); + } else if (H5Tequal(type, H5T_STD_I32LE)) { + printf("H5T_STD_I32LE"); + } else if (H5Tequal(type, H5T_STD_I64BE)) { + printf("H5T_STD_I64BE"); + } else if (H5Tequal(type, H5T_STD_I64LE)) { + printf("H5T_STD_I64LE"); + } else if (H5Tequal(type, H5T_STD_U8BE)) { + printf("H5T_STD_U8BE"); + } else if (H5Tequal(type, H5T_STD_U8LE)) { + printf("H5T_STD_U8LE"); + } else if (H5Tequal(type, H5T_STD_U16BE)) { + printf("H5T_STD_U16BE"); + } else if (H5Tequal(type, H5T_STD_U16LE)) { + printf("H5T_STD_U16LE"); + } else if (H5Tequal(type, H5T_STD_U32BE)) { + printf("H5T_STD_U32BE"); + } else if (H5Tequal(type, H5T_STD_U32LE)) { + printf("H5T_STD_U32LE"); + } else if (H5Tequal(type, H5T_STD_U64BE)) { + printf("H5T_STD_U64BE"); + } else if (H5Tequal(type, H5T_STD_U64LE)) { + printf("H5T_STD_U64LE"); + } else if (H5Tequal(type, H5T_NATIVE_SCHAR)) { + printf("H5T_NATIVE_SCHAR"); + } else if (H5Tequal(type, H5T_NATIVE_UCHAR)) { + printf("H5T_NATIVE_UCHAR"); + } else if (H5Tequal(type, H5T_NATIVE_SHORT)) { + printf("H5T_NATIVE_SHORT"); + } else if (H5Tequal(type, H5T_NATIVE_USHORT)) { + printf("H5T_NATIVE_USHORT"); + } else if (H5Tequal(type, H5T_NATIVE_INT)) { + printf("H5T_NATIVE_INT"); + } else if (H5Tequal(type, H5T_NATIVE_UINT)) { + printf("H5T_NATIVE_UINT"); + } else if (H5Tequal(type, H5T_NATIVE_LONG)) { + printf("H5T_NATIVE_LONG"); + } else if (H5Tequal(type, H5T_NATIVE_ULONG)) { + printf("H5T_NATIVE_ULONG"); + } else if (H5Tequal(type, H5T_NATIVE_LLONG)) { + printf("H5T_NATIVE_LLONG"); + } else if (H5Tequal(type, H5T_NATIVE_ULLONG)) { + printf("H5T_NATIVE_ULLONG"); + } else { + printf("undefined integer"); + d_status = EXIT_FAILURE; + } + break; + + case H5T_FLOAT: + if (H5Tequal(type, H5T_IEEE_F32BE)) { + printf("H5T_IEEE_F32BE"); + } else if (H5Tequal(type, H5T_IEEE_F32LE)) { + printf("H5T_IEEE_F32LE"); + } else if (H5Tequal(type, H5T_IEEE_F64BE)) { + printf("H5T_IEEE_F64BE"); + } else if (H5Tequal(type, H5T_IEEE_F64LE)) { + printf("H5T_IEEE_F64LE"); + } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) { + printf("H5T_NATIVE_FLOAT"); + } else if (H5Tequal(type, H5T_NATIVE_DOUBLE)) { + printf("H5T_NATIVE_DOUBLE"); + } else if (H5Tequal(type, H5T_NATIVE_LDOUBLE)) { + printf("H5T_NATIVE_LDOUBLE"); + } else { + printf("undefined float"); + d_status = EXIT_FAILURE; + } + break; + + case H5T_TIME: + printf("H5T_TIME: not yet implemented"); + break; + + case H5T_STRING: + size = H5Tget_size(type); + str_pad = H5Tget_strpad(type); + cset = H5Tget_cset(type); + + printf("H5T_STRING %s\n", dump_header_format->strblockbegin); + indent += COL; + + indentation(indent + COL); + printf("%s %d;\n", STRSIZE, (int) size); + + indentation(indent + COL); + printf("%s ", STRPAD); + if (str_pad == H5T_STR_NULLTERM) + printf("H5T_STR_NULLTERM;\n"); + else if (str_pad == H5T_STR_NULLPAD) + printf("H5T_STR_NULLPAD;\n"); + else if (str_pad == H5T_STR_SPACEPAD) + printf("H5T_STR_SPACEPAD;\n"); + else + printf("H5T_STR_ERROR;\n"); + + indentation(indent + COL); + printf("%s ", CSET); + + if (cset == H5T_CSET_ASCII) + printf("H5T_CSET_ASCII;\n"); + else + printf("unknown_cset;\n"); + + str_type = H5Tcopy(H5T_C_S1); + H5Tset_cset(str_type, cset); + H5Tset_size(str_type, size); + H5Tset_strpad(str_type, str_pad); + + indentation(indent + COL); + printf("%s ", CTYPE); + + if (H5Tequal(type, str_type)) { + printf("H5T_C_S1;\n"); + H5Tclose(str_type); + } else { + H5Tclose(str_type); + str_type = H5Tcopy(H5T_FORTRAN_S1); + H5Tset_cset(str_type, cset); + H5Tset_size(str_type, size); + H5Tset_strpad(str_type, str_pad); + + if (H5Tequal(type, str_type)) { + printf("H5T_FORTRAN_S1;\n"); + } else { + printf("unknown_one_character_type;\n "); + d_status = EXIT_FAILURE; + } + + H5Tclose(str_type); + } + + indent -= COL; + indentation(indent + COL); + printf("%s", dump_header_format->strblockend); + break; + + case H5T_BITFIELD: + if (H5Tequal(type, H5T_STD_B8BE)) { + printf("H5T_STD_B8BE"); + } else if (H5Tequal(type, H5T_STD_B8LE)) { + printf("H5T_STD_B8LE"); + } else if (H5Tequal(type, H5T_STD_B16BE)) { + printf("H5T_STD_B16BE"); + } else if (H5Tequal(type, H5T_STD_B16LE)) { + printf("H5T_STD_B16LE"); + } else if (H5Tequal(type, H5T_STD_B32BE)) { + printf("H5T_STD_B32BE"); + } else if (H5Tequal(type, H5T_STD_B32LE)) { + printf("H5T_STD_B32LE"); + } else if (H5Tequal(type, H5T_STD_B64BE)) { + printf("H5T_STD_B64BE"); + } else if (H5Tequal(type, H5T_STD_B64LE)) { + printf("H5T_STD_B64LE"); + } else { + printf("undefined bitfield"); + d_status = EXIT_FAILURE; + } + break; + + case H5T_OPAQUE: + printf("\n"); + indentation(indent + COL); + printf("H5T_OPAQUE;\n"); + indentation(indent + COL); + printf("OPAQUE_TAG \"%s\";\n", H5Tget_tag(type)); + indentation(indent); + break; + + case H5T_COMPOUND: + if (H5Tcommitted(type) > 0) { + H5Gget_objinfo(type, ".", TRUE, &statbuf); + i = search_obj(type_table, statbuf.objno); + + if (i >= 0) { + if (!type_table->objs[i].recorded) + printf("\"/#%lu:%lu\"\n", type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + else + printf("\"%s\"", type_table->objs[i].objname); + } else { + error_msg(progname, "unknown committed type.\n"); + d_status = EXIT_FAILURE; + } + } else { + nmembers = H5Tget_nmembers(type); + printf("H5T_COMPOUND %s\n", dump_header_format->structblockbegin); + + for (i = 0; i < nmembers; i++) { + fname = H5Tget_member_name(type, i); + mtype = H5Tget_member_type(type, i); + + indentation(indent + COL); + + if (H5Tget_class(mtype) == H5T_COMPOUND) + indent += COL; + + print_datatype(mtype); + + if (H5Tget_class(mtype) == H5T_COMPOUND) + indent -= COL; + + printf(" \"%s\";\n", fname); + free(fname); + } + + indentation(indent); + printf("%s", dump_header_format->structblockend); + } + + break; + + case H5T_REFERENCE: + printf("H5T_REFERENCE"); + break; + + case H5T_ENUM: + printf("H5T_ENUM %s\n", dump_header_format->enumblockbegin); + indent += COL; + indentation(indent + COL); + super = H5Tget_super(type); + print_datatype(super); + printf(";\n"); + print_enum(type); + indent -= COL; + indentation(indent + COL); + printf("%s", dump_header_format->enumblockend); + break; + + case H5T_VLEN: + printf("H5T_VLEN %s ", dump_header_format->vlenblockbegin); + super = H5Tget_super(type); + print_datatype(super); + H5Tclose(super); + + /* Print closing */ + printf("%s", dump_header_format->vlenblockend); + break; + + case H5T_ARRAY: + /* Get array base type */ + super = H5Tget_super(type); + + /* Print lead-in */ + printf("H5T_ARRAY { "); + + /* Get array information */ + ndims = H5Tget_array_ndims(type); + H5Tget_array_dims(type, dims, perm); + + /* Print array dimensions */ + for (j = 0; j < ndims; j++) + printf("[%d]", (int) dims[j]); + + printf(" "); + + /* Print base type */ + print_datatype(super); + + /* Close array base type */ + H5Tclose(super); + + /* Print closing */ + printf(" }"); + + break; + + default: + printf("unknown data type"); + d_status = EXIT_FAILURE; + break; + } +} + +/*------------------------------------------------------------------------- + * Function: dump_bb + * + * Purpose: Dump the boot block + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_bb(void) +{ + printf("%s %s boot block not yet implemented %s\n", + BOOT_BLOCK, BEGIN, END); +} + +/*------------------------------------------------------------------------- + * Function: dump_datatype + * + * Purpose: Dump the data type. Data type can be HDF5 predefined + * atomic data type or committed/transient data type. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_datatype(hid_t type) +{ + indent += COL; + + indentation(indent); + printf("%s %s ", dump_header_format->datatypebegin, + dump_header_format->datatypeblockbegin); + + print_datatype(type); + + if (H5Tget_class(type) == H5T_COMPOUND || H5Tget_class(type) == H5T_STRING) + indentation(indent); + + printf(" %s %s\n", dump_header_format->datatypeblockend, + dump_header_format->datatypeend); + indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: dump_dataspace + * + * Purpose: Dump the data space. Data space can be named data space, + * array, or others. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_dataspace(hid_t space) +{ + hsize_t size[H5DUMP_MAX_RANK]; + hsize_t maxsize[H5DUMP_MAX_RANK]; + int ndims = H5Sget_simple_extent_dims(space, size, maxsize); + int i; + + indentation(indent + COL); + printf("%s ", dump_header_format->dataspacebegin); + + if (H5Sis_simple(space)) { + if (ndims == 0) { + /* scalar dataspace */ + HDfprintf(stdout, "%s %s ", + dump_header_format->dataspacedescriptionbegin, SCALAR); + } else { + /* simple dataspace */ + HDfprintf(stdout, "%s %s { %s %Hu", + dump_header_format->dataspacedescriptionbegin, SIMPLE, + dump_header_format->dataspacedimbegin, size[0]); + + for (i = 1; i < ndims; i++) + HDfprintf(stdout, ", %Hu", size[i]); + + printf(" %s / ", dump_header_format->dataspacedimend); + + if (maxsize[0] == H5S_UNLIMITED) + HDfprintf(stdout, "%s %s", + dump_header_format->dataspacedimbegin, + "H5S_UNLIMITED"); + else + HDfprintf(stdout, "%s %Hu", + dump_header_format->dataspacedimbegin, maxsize[0]); + + for (i = 1; i < ndims; i++) + if (maxsize[i] == H5S_UNLIMITED) + HDfprintf(stdout, ", %s", "H5S_UNLIMITED"); + else + HDfprintf(stdout, ", %Hu", maxsize[i]); + + printf(" %s }", dump_header_format->dataspacedimend); + } + } else { + printf("%s not yet implemented %s\n", BEGIN, END); + } + + end_obj(dump_header_format->dataspaceend, + dump_header_format->dataspaceblockend); +} + +/*------------------------------------------------------------------------- + * Function: dump_attr + * + * Purpose: dump the attribute + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_attr(hid_t attr, const char *attr_name, void UNUSED * op_data) +{ + hid_t attr_id, type, space; + herr_t ret = SUCCEED; + + indentation(indent); + begin_obj(dump_header_format->attributebegin, attr_name, + dump_header_format->attributeblockbegin); + + if ((attr_id = H5Aopen_name(attr, attr_name)) < 0) { + indentation(indent + COL); + error_msg(progname, "unable to open attribute \"%s\"\n", attr_name); + indentation(indent); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + ret = FAIL; + } else { + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + dump_datatype(type); + dump_dataspace(space); + + if (display_oid) + dump_oid(attr_id); + + if (display_data) + dump_data(attr_id, ATTRIBUTE_DATA); + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr_id); + indentation(indent); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + } + + return ret; +} + +/*------------------------------------------------------------------------- + * Function: dump_selected_attr + * + * Purpose: dump the selected attribute + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_selected_attr(hid_t loc_id, const char *name) +{ + int j; + char *obj_name; + const char *attr_name; + hid_t oid, attr_id, type, space; + H5G_stat_t statbuf; + + j = (int)strlen(name) - 1; + obj_name = malloc((size_t)j + 2); + + /* find the last / */ + while (name[j] != '/' && j >= 0) + j--; + + /* object name */ + if (j == -1) { + strcpy(obj_name, "/"); + } else { + strncpy(obj_name, name, (size_t)j + 1); + obj_name[j + 1] = '\0'; + } + + attr_name = name + j + 1; + begin_obj(dump_header_format->attributebegin, name, + dump_header_format->attributeblockbegin); + H5Gget_objinfo(loc_id, obj_name, FALSE, &statbuf); + + switch (statbuf.type) { + case H5G_GROUP: + if ((oid = H5Gopen(loc_id, obj_name)) < 0) { + indentation(COL); + error_msg(progname, "unable to open group \"%s\"\n", obj_name); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + return FAIL; + } + break; + + case H5G_DATASET: + if ((oid = H5Dopen(loc_id, obj_name)) < 0) { + indentation(COL); + error_msg(progname, "unable to open dataset \"%s\"\n", obj_name); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + return FAIL; + } + break; + + case H5G_TYPE: + if ((oid = H5Topen(loc_id, obj_name)) < 0) { + indentation(COL); + error_msg(progname, "unable to open datatype \"%s\"\n", obj_name); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + return FAIL; + } + break; + + default: + indentation(COL); + error_msg(progname, "unable to open unknown \"%s\"\n", obj_name); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + return FAIL; + } + + if ((attr_id = H5Aopen_name(oid, attr_name)) >= 0) { + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + dump_datatype(type); + dump_dataspace(space); + + if (display_oid) + dump_oid(attr_id); + + if (display_data) + dump_data(attr_id, ATTRIBUTE_DATA); + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr_id); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + } else { + indentation(COL); + error_msg(progname, "unable to open attribute \"%s\"\n", obj_name); + end_obj(dump_header_format->attributeend, + dump_header_format->attributeblockend); + d_status = EXIT_FAILURE; + } + + switch (statbuf.type) { + case H5G_GROUP: + if (H5Gclose(oid) < 0) { + d_status = EXIT_FAILURE; + return FAIL; + } + break; + + case H5G_DATASET: + if (H5Dclose(oid) < 0) { + d_status = EXIT_FAILURE; + return FAIL; + } + break; + + case H5G_TYPE: + if (H5Tclose(oid) < 0) { + d_status = EXIT_FAILURE; + return FAIL; + } + break; + default: + d_status = EXIT_FAILURE; + return FAIL; + } + + free(obj_name); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: dump_all + * + * Purpose: Dump everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * RMcG, November 2000 + * Added XML support. Also, optionally checks the op_data + * argument. + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_all(hid_t group, const char *name, void * op_data) +{ + hid_t obj; + char *buf, *tmp = NULL; + H5G_stat_t statbuf; + int i; + herr_t ret = SUCCEED; + + H5Gget_objinfo(group, name, FALSE, &statbuf); + + if (*(int *)op_data != H5G_UNKNOWN && statbuf.type != *(int *) op_data) + goto done; + + tmp = malloc(strlen(prefix) + strlen(name) + 1); + strcpy(tmp, prefix); + + switch (statbuf.type) { + case H5G_LINK: + indentation(indent); + buf = malloc(statbuf.linklen); + + if (!doxml) { + begin_obj(dump_header_format->softlinkbegin, name, + dump_header_format->softlinkblockbegin); + indentation(indent + COL); + } + + if (H5Gget_linkval(group, name, statbuf.linklen, buf) < 0) { + error_msg(progname, "unable to get link value\n"); + d_status = EXIT_FAILURE; + ret = FAIL; + } else { + /* print the value of a soft link */ + if (!doxml) { + /* Standard DDL: no modification */ + printf("LINKTARGET \"%s\"\n", buf); + } else { + /* XML */ + char *t_name = xml_escape_the_name(name); + char *t_buf = xml_escape_the_name(buf); + char *t_prefix = xml_escape_the_name(prefix); + char *tmp2, *t_tmp2, *t_tmp; + + tmp2 = malloc(strlen(prefix) + statbuf.linklen + 1); + strcpy(tmp2, prefix); + + if (buf && buf[0] == '/') + strcat(tmp2, buf); + else + strcat(strcat(tmp2, "/"), buf); + + t_tmp = xml_escape_the_name(strcat(strcat(tmp, "/"), name)); + t_tmp2 = xml_escape_the_name(tmp2); + + printf("\n", + t_name, t_buf, t_tmp2, t_tmp, + (strcmp(prefix, "") ? t_prefix : "root")); + + free(t_name); + free(t_buf); + free(t_prefix); + free(t_tmp); + free(t_tmp2); + free(tmp2); + } + } + + if (!doxml) { + indentation(indent); + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + } + + free(buf); + break; + + case H5G_GROUP: + if ((obj = H5Gopen(group, name)) < 0) { + error_msg(progname, "unable to dump group \"%s\"\n", name); + d_status = EXIT_FAILURE; + ret = FAIL; + } else { + strcat(strcat(prefix, "/"), name); + dump_function_table->dump_group_function(obj, name); + strcpy(prefix, tmp); + H5Gclose(obj); + } + + break; + + case H5G_DATASET: + if ((obj = H5Dopen(group, name)) >= 0) { + /* hard link */ + H5Gget_objinfo(obj, ".", TRUE, &statbuf); + + if (statbuf.nlink > 1) { + i = search_obj(dset_table, statbuf.objno); + + if (i < 0) { + indentation(indent); + begin_obj(dump_header_format->datasetbegin, name, + dump_header_format->datasetblockbegin); + indentation(indent + COL); + error_msg(progname, + "internal error (file %s:line %d)\n", + __FILE__, __LINE__); + indentation(indent); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + d_status = EXIT_FAILURE; + ret = FAIL; + H5Dclose(obj); + goto done; + } else if (dset_table->objs[i].displayed) { + indentation(indent); + if (!doxml) { + begin_obj(dump_header_format->datasetbegin, name, + dump_header_format->datasetblockbegin); + indentation(indent + COL); + printf("%s \"%s\"\n", HARDLINK, + dset_table->objs[i].objname); + indentation(indent); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + } else { + /* the XML version */ + char *t_name = xml_escape_the_name(name); + char *t_tmp = xml_escape_the_name(strcat(strcat(tmp, "/"), name)); + char *t_prefix = xml_escape_the_name(prefix); + char *t_objname = xml_escape_the_name(dset_table->objs[i].objname); + + printf("\n", + t_name, t_tmp, + (strcmp(prefix, "") ? t_prefix : "root")); + + indentation(indent + COL); + printf("\n", t_objname); + indentation(indent); + printf("%s\n", dump_header_format->datasetend); + + free(t_name); + free(t_tmp); + free(t_prefix); + free(t_objname); + } + + H5Dclose(obj); + goto done; + } else { + dset_table->objs[i].displayed = 1; + strcat(tmp, "/"); + strcat(tmp, name); + strcpy(dset_table->objs[i].objname, tmp); + } + } + + dump_function_table->dump_dataset_function(obj, name); + H5Dclose(obj); + } else { + error_msg(progname, "unable to dump dataset \"%s\"\n", name); + d_status = EXIT_FAILURE; + ret = FAIL; + } + + break; + + case H5G_TYPE: + if ((obj = H5Topen(group, name)) < 0) { + error_msg(progname, "unable to dump data type \"%s\"\n", name); + d_status = EXIT_FAILURE; + ret = FAIL; + } else { + dump_function_table->dump_named_datatype_function(obj, name); + H5Tclose(obj); + } + + break; + + default: + error_msg(progname, "unknown object \"%s\"\n", name); + d_status = EXIT_FAILURE; + ret = FAIL; + } + +done: + free(tmp); + return ret; +} + +/*------------------------------------------------------------------------- + * Function: dump_named_datatype + * + * Purpose: Dump named data type + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: Comments: not yet implemented. + * + *------------------------------------------------------------------------- + */ +static void +dump_named_datatype(hid_t type, const char *name) +{ + indentation(indent); + printf("%s \"%s\" %s", dump_header_format->datatypebegin, name, + dump_header_format->datatypeblockbegin); + + if (H5Tget_class(type) == H5T_COMPOUND) { + hid_t temp_type = H5Tcopy(type); + + print_datatype(temp_type); + H5Tclose(temp_type); + } else { + indentation(indent + COL); + print_datatype(type); + printf(";\n"); + } + + indentation(indent); + end_obj(dump_header_format->datatypeend, + dump_header_format->datatypeblockend); +} + +/*------------------------------------------------------------------------- + * Function: dump_group + * + * Purpose: Dump everything within the specified group + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + * Call to dump_all -- add parameter to select everything. + * + *------------------------------------------------------------------------- + */ +static void +dump_group(hid_t gid, const char *name) +{ + H5G_stat_t statbuf; + hid_t dset, type; + char typename[1024], *tmp; + int i, xtype = H5G_UNKNOWN; /* dump all */ + + tmp = malloc(strlen(prefix) + strlen(name) + 2); + strcpy(tmp, prefix); + indentation(indent); + begin_obj(dump_header_format->groupbegin, name, + dump_header_format->groupblockbegin); + indent += COL; + + if (display_oid) + dump_oid(gid); + + if (!strcmp(name, "/") && unamedtype) + /* dump unamed type in root group */ + for (i = 0; i < type_table->nobjs; i++) + if (!type_table->objs[i].recorded) { + dset = H5Dopen(gid, type_table->objs[i].objname); + type = H5Dget_type(dset); + sprintf(typename, "#%lu:%lu", + type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + dump_named_datatype(type, typename); + H5Tclose(type); + H5Dclose(dset); + } + + H5Gget_objinfo(gid, ".", TRUE, &statbuf); + + if (statbuf.nlink > 1) { + i = search_obj(group_table, statbuf.objno); + + if (i < 0) { + indentation(indent); + error_msg(progname, "internal error (file %s:line %d)\n", + __FILE__, __LINE__); + d_status = EXIT_FAILURE; + } else if (group_table->objs[i].displayed) { + indentation(indent); + printf("%s \"%s\"\n", HARDLINK, group_table->objs[i].objname); + } else { + strcpy(group_table->objs[i].objname, prefix); + group_table->objs[i].displayed = 1; + H5Aiterate(gid, NULL, dump_attr, NULL); + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + } + } else { + H5Aiterate(gid, NULL, dump_attr, NULL); + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + } + + indent -= COL; + indentation(indent); + end_obj(dump_header_format->groupend, dump_header_format->groupblockend); + free(tmp); +} + +/*------------------------------------------------------------------------- + * Function: dump_dataset + * + * Purpose: Dump the specified data set + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_dataset(hid_t did, const char *name) +{ + hid_t type, space; + + indentation(indent); + begin_obj(dump_header_format->datasetbegin, name, + dump_header_format->datasetblockbegin); + type = H5Dget_type(did); + space = H5Dget_space(did); + dump_datatype(type); + dump_dataspace(space); + + if (display_oid) + dump_oid(did); + + if (display_data) + switch (H5Tget_class(type)) { + case H5T_TIME: + indentation(indent + COL); + printf("DATA{ not yet implemented.}\n"); + break; + + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_COMPOUND: + case H5T_REFERENCE: + case H5T_ENUM: + case H5T_VLEN: + case H5T_ARRAY: + dump_data(did, DATASET_DATA); + break; + + default: + break; + } + + indent += COL; + H5Aiterate(did, NULL, dump_attr, NULL); + indent -= COL; + H5Tclose(type); + H5Sclose(space); + indentation(indent); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); +} + +/*------------------------------------------------------------------------- + * Function: dump_tables + * + * Purpose: display the contents of tables for debugging purposes + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_tables(void) +{ +#ifdef H5DUMP_DEBUG + register int i; + + printf("group_table: # of entries = %d\n", group_table->nobjs); + + for (i = 0; i < group_table->nobjs; i++) + printf("%lu %lu %s %d %d\n", group_table->objs[i].objno[0], + group_table->objs[i].objno[1], + group_table->objs[i].objname, + group_table->objs[i].displayed, group_table->objs[i].recorded); + + printf("\ndset_table: # of entries = %d\n", dset_table->nobjs); + + for (i = 0; i < dset_table->nobjs; i++) + printf("%lu %lu %s %d %d\n", dset_table->objs[i].objno[0], + dset_table->objs[i].objno[1], + dset_table->objs[i].objname, + dset_table->objs[i].displayed, dset_table->objs[i].recorded); + + printf("\ntype_table: # of entries = %d\n", type_table->nobjs); + + for (i = 0; i < type_table->nobjs; i++) + printf("%lu %lu %s %d %d\n", type_table->objs[i].objno[0], + type_table->objs[i].objno[1], + type_table->objs[i].objname, + type_table->objs[i].displayed, type_table->objs[i].recorded); +#else + return; +#endif /* H5DUMP_DEBUG */ +} + +/*------------------------------------------------------------------------- + * Function: dump_data + * + * Purpose: Dump attribute or dataset data + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_data(hid_t obj_id, int obj_data) +{ + h5dump_t *outputformat = &dataformat; + int status = -1; + void *buf; + hid_t space, type, p_type; + int ndims, i; + hsize_t size[64], nelmts = 1, alloc_size; + int depth; + int stdindent = COL; /* should be 3 */ + + outputformat->line_ncols = nCols; + indent += COL; + + /* + * the depth will tell us how far we need to indent extra. we use to just + * use indent but with the merging of the tools lib we have to do + * something different for the lib funtions... the normal indentation is 6 + * so when we don't need any extra indentation, depth will be 0. + */ + depth = indent / stdindent + 1; + indentation(indent); + begin_obj(dump_header_format->databegin, (const char *) NULL, + dump_header_format->datablockbegin); + + /* Print all the values. */ + if (obj_data == DATASET_DATA) { + status = h5dump_dset(stdout, outputformat, obj_id, -1, depth); + } else { + /* need to call h5dump_mem for the attribute data */ + type = H5Aget_type(obj_id); + p_type = h5dump_fixtype(type); + space = H5Aget_space(obj_id); + ndims = H5Sget_simple_extent_dims(space, size, NULL); + + for (i = 0; i < ndims; i++) + nelmts *= size[i]; + + alloc_size = nelmts * MAX(H5Tget_size(type), H5Tget_size(p_type)); + assert(alloc_size == (hsize_t)((size_t)alloc_size)); /*check for overflow*/ + buf = malloc((size_t)alloc_size); + assert(buf); + + if (H5Aread(obj_id, p_type, buf) >= 0) + status = h5dump_mem(stdout, outputformat, obj_id, p_type, space, buf, depth); + + free(buf); + H5Tclose(p_type); + H5Sclose(space); + H5Tclose(type); + } + + if (status < 0) { + indentation(indent + COL); + error_msg(progname, "unable to print data\n"); + d_status = EXIT_FAILURE; + } + + indentation(indent); + end_obj(dump_header_format->dataend, dump_header_format->datablockend); + indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: dump_oid + * + * Purpose: Prints the object ids + * + * Return: void + * + * Programmer: Patrick Lu + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +dump_oid(hid_t oid) +{ + indentation(indent + COL); + printf("%s %s %d %s\n", OBJID, BEGIN, oid, END); +} + +/*------------------------------------------------------------------------- + * Function: set_output_file + * + * Purpose: Open fname as the output file for dataset raw data. + * Set rawdatastream as its file stream. + * + * Return: 0 -- succeeded + * negative -- failed + * + * Programmer: Albert Cheng, 2000/09/30 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +set_output_file(const char *fname) +{ + FILE *f; /* temporary holding place for the stream pointer + * so that rawdatastream is changed only when succeeded */ + + if ((f = fopen(fname, "w")) != NULL) { + rawdatastream = f; + return 0; + } + + return -1; +} + +/*------------------------------------------------------------------------- + * Function: handle_attributes + * + * Purpose: Handle the attributes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +handle_attributes(hid_t fid, char *attr, void UNUSED *data) +{ + dump_selected_attr(fid, attr); +} + +/*------------------------------------------------------------------------- + * Function: parse_hsize_list + * + * Purpose: Parse a list of comma or space separated integers and return + * them in a list. The string being passed into this function + * should be at the start of the list you want to parse. You are + * responsible for freeing the array returned from here. + * + * Lists in the so-called "terse" syntax are separated by + * semicolons (;). The lists themselves can be separated by + * either commas (,) or white spaces. + * + * Return: Success: hsize_t array. NULL is a valid return type if + * there aren't any elements in the array. + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hsize_t * +parse_hsize_list(const char *h_list) +{ + hsize_t *p_list; + const char *ptr; + unsigned int size_count = 0, i = 0, last_digit = 0; + + if (!h_list || !*h_list || *h_list == ';') + return NULL; + + /* count how many integers do we have */ + for (ptr = h_list; ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if (isdigit(*ptr)) { + if (!last_digit) + /* the last read character wasn't a digit */ + size_count++; + + last_digit = 1; + } else { + last_digit = 0; + } + + if (size_count == 0) + /* there aren't any integers to read */ + return NULL; + + /* allocate an array for the integers in the list */ + p_list = calloc(size_count, sizeof(hsize_t)); + + for (ptr = h_list; i < size_count && ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if (isdigit(*ptr)) { + /* we should have an integer now */ + p_list[i++] = (hsize_t)atoi(ptr); + + while (isdigit(*ptr)) + /* scroll to end of integer */ + ptr++; + } + + return p_list; +} + +/*------------------------------------------------------------------------- + * Function: parse_subset_params + * + * Purpose: Parse the so-called "terse" syntax for specifying subsetting + * parameters. + * + * Return: Success: struct subset_t object + * Failure: NULL + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static struct subset_t * +parse_subset_params(char *dset) +{ + struct subset_t *s = NULL; + register char *brace; + + if ((brace = strrchr(dset, '[')) != NULL) { + char *slash = strrchr(dset, '/'); + + /* sanity check to make sure the [ isn't part of the dataset name */ + if (brace > slash) { + *brace++ = '\0'; + s = calloc(1, sizeof(struct subset_t)); + + printf("start\n"); + s->start = parse_hsize_list(brace); + + while (*brace && *brace != ';') + brace++; + + if (*brace) + brace++; + + printf("stride\n"); + s->stride = parse_hsize_list(brace); + + while (*brace && *brace != ';') + brace++; + + if (*brace) + brace++; + + printf("count\n"); + s->count = parse_hsize_list(brace); + + while (*brace && *brace != ';') + brace++; + + if (*brace) + brace++; + + printf("block\n"); + s->block = parse_hsize_list(brace); + } + } + + return s; +} + +/*------------------------------------------------------------------------- + * Function: handle_datasets + * + * Purpose: Handle the datasets from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +handle_datasets(hid_t fid, char *dset, void *data) +{ + H5G_stat_t statbuf; + hid_t dsetid; + struct subset_t *sset = (struct subset_t *)data; + + if ((dsetid = H5Dopen(fid, dset)) < 0) { + begin_obj(dump_header_format->datasetbegin, dset, + dump_header_format->datasetblockbegin); + indentation(COL); + error_msg(progname, "unable to open dataset \"%s\"\n", dset); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + d_status = EXIT_FAILURE; + } else { + H5Gget_objinfo(dsetid, ".", TRUE, &statbuf); + + if (statbuf.nlink > 1) { + int index = search_obj(dset_table, statbuf.objno); + + if (index >= 0) { + if (dset_table->objs[index].displayed) { + begin_obj(dump_header_format->datasetbegin, dset, + dump_header_format->datasetblockbegin); + indentation(indent + COL); + printf("%s \"%s\"\n", HARDLINK, + dset_table->objs[index].objname); + indentation(indent); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + } else { + strcpy(dset_table->objs[index].objname, dset); + dset_table->objs[index].displayed = 1; + dump_dataset(dsetid, dset); + } + } else { + d_status = EXIT_FAILURE; + } + } else { + dump_dataset(dsetid, dset); + } + + if (H5Dclose(dsetid) < 1) + d_status = EXIT_FAILURE; + } +} + +/*------------------------------------------------------------------------- + * Function: handle_groups + * + * Purpose: Handle the groups from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +handle_groups(hid_t fid, char *group, void UNUSED *data) +{ + H5G_stat_t statbuf; + hid_t gid; + + if ((gid = H5Gopen(fid, group)) < 0) { + begin_obj(dump_header_format->groupbegin, group, + dump_header_format->groupblockbegin); + indentation(COL); + error_msg(progname, "unable to open group \"%s\"\n", group); + end_obj(dump_header_format->groupend, + dump_header_format->groupblockend); + d_status = EXIT_FAILURE; + } else { + H5Gget_objinfo(gid, ".", TRUE, &statbuf); + strcpy(prefix, group); + dump_group(gid, group); + + if (H5Gclose(gid) < 0) + d_status = EXIT_FAILURE; + } +} + +/*------------------------------------------------------------------------- + * Function: handle_links + * + * Purpose: Handle the links from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +handle_links(hid_t fid, char *links, void UNUSED *data) +{ + H5G_stat_t statbuf; + + if (H5Gget_objinfo(fid, links, FALSE, &statbuf) < 0) { + begin_obj(dump_header_format->softlinkbegin, links, + dump_header_format->softlinkblockbegin); + indentation(COL); + error_msg(progname, "unable to get obj info from \"%s\"\n", links); + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + d_status = EXIT_FAILURE; + } else if (statbuf.type == H5G_LINK) { + char *buf = malloc(statbuf.linklen); + + begin_obj(dump_header_format->softlinkbegin, links, + dump_header_format->softlinkblockbegin); + indentation(COL); + + if (H5Gget_linkval(fid, links, statbuf.linklen, buf) >= 0) { + printf("LINKTARGET \"%s\"\n", buf); + } else { + error_msg(progname, "h5dump error: unable to get link value for \"%s\"\n", + links); + d_status = EXIT_FAILURE; + } + + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + free(buf); + } else { + begin_obj(dump_header_format->softlinkbegin, links, + dump_header_format->softlinkblockbegin); + indentation(COL); + error_msg(progname, "\"%s\" is not a link\n", links); + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + d_status = EXIT_FAILURE; + } +} + +/*------------------------------------------------------------------------- + * Function: handle_datatypes + * + * Purpose: Handle the datatypes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +handle_datatypes(hid_t fid, char *type, void UNUSED *data) +{ + hid_t typeid; + + if ((typeid = H5Topen(fid, type)) < 0) { + /* check if type is unamed data type */ + int index = 0; + + while (index < type_table->nobjs ) { + char name[128], name1[128]; + + if (!type_table->objs[index].recorded) { + /* unamed data type */ + sprintf(name, "#%lu:%lu\n", + type_table->objs[index].objno[0], + type_table->objs[index].objno[1]); + sprintf(name1, "/#%lu:%lu\n", + type_table->objs[index].objno[0], + type_table->objs[index].objno[1]); + + if (!strncmp(name, type, strlen(type)) || + !strncmp(name1, type, strlen(type))) + break; + } + + index++; + } + + if (index == type_table->nobjs) { + /* unknown type */ + begin_obj(dump_header_format->datatypebegin, type, + dump_header_format->datatypeblockbegin); + indentation(COL); + error_msg(progname, "unable to open datatype \"%s\"\n", type); + end_obj(dump_header_format->datatypeend, + dump_header_format->datatypeblockend); + d_status = EXIT_FAILURE; + } else { + hid_t dsetid = H5Dopen(fid, type_table->objs[index].objname); + typeid = H5Dget_type(dsetid); + dump_named_datatype(typeid, type); + H5Tclose(typeid); + H5Dclose(dsetid); + } + } else { + dump_named_datatype(typeid, type); + + if (H5Tclose(typeid) < 0) + d_status = EXIT_FAILURE; + } +} + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parse the command line for the h5dumper. + * + * Return: Success: A pointer to an array of handler_t structures. + * These contain all the information needed to dump + * the necessary object. + * + * Failure: Exits program with EXIT_FAILURE value. + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static struct handler_t * +parse_command_line(int argc, const char *argv[]) +{ + struct handler_t *hand, *last_dset; + int i, opt, last_was_dset = FALSE; + + if (argc < 2) { + usage(progname); + exit(EXIT_FAILURE); + } + + /* this will be plenty big enough to hold the info */ + hand = calloc((size_t)argc, sizeof(struct handler_t)); + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { +parse_start: + switch ((char)opt) { + case 'B': + display_bb = TRUE; + last_was_dset = FALSE; + break; + case 'H': + display_data = FALSE; + last_was_dset = FALSE; + break; + case 'v': + display_oid = TRUE; + last_was_dset = FALSE; + break; + case 'V': + print_version(progname); + exit(EXIT_SUCCESS); + break; + case 'w': + nCols = atoi(opt_arg); + last_was_dset = FALSE; + break; + case 'a': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_attributes; + hand[i].obj = strdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'd': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datasets; + hand[i].obj = strdup(opt_arg); + hand[i].subset_info = parse_subset_params(hand[i].obj); + last_dset = hand; + break; + } + + last_was_dset = TRUE; + break; + case 'g': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_groups; + hand[i].obj = strdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'l': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_links; + hand[i].obj = strdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 't': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datatypes; + hand[i].obj = strdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'o': + if (set_output_file(opt_arg) < 0){ + /* failed to set output file */ + usage(progname); + exit(EXIT_FAILURE); + } + + usingdasho = TRUE; + last_was_dset = FALSE; + break; + + /** XML parameters **/ + case 'x': + /* select XML output */ + doxml = TRUE; + dump_header_format = &xmlformat; + dump_function_table = &xml_function_table; + break; + case 'D': + /* specify alternative XML DTD */ + xml_dtd_uri = opt_arg; + break; + /** end XML parameters **/ + + /** subsetting parameters **/ + case 's': + case 'T': + case 'c': + case 'k': { + struct subset_t *s; + + if (!last_was_dset) { + error_msg(progname, + "option `-%c' can only be used after --dataset option\n", + opt); + exit(EXIT_FAILURE); + } + + if (last_dset->subset_info) { + /* + * This overrides the "terse" syntax if they actually mixed + * the two. + */ + s = last_dset->subset_info; + } else { + last_dset->subset_info = s = calloc(1, sizeof(struct subset_t)); + } + + /* + * slightly convoluted, but...we are only interested in options + * for subsetting: "--start", "--stride", "--count", and "--block" + * which can come in any order. If we run out of parameters (EOF) + * or run into one which isn't a subsetting parameter (NOT s, T, + * c, or K), then we exit the do-while look, set the subset_info + * to the structure we've been filling. If we've reached the end + * of the options, we exit the parsing (goto parse_end) otherwise, + * since we've "read" the next option, we need to parse it. So we + * jump to the beginning of the switch statement (goto parse_start). + */ + do { + switch ((char)opt) { + case 's': free(s->start); s->start = parse_hsize_list(opt_arg); break; + case 'T': free(s->stride); s->stride = parse_hsize_list(opt_arg); break; + case 'c': free(s->count); s->count = parse_hsize_list(opt_arg); break; + case 'k': free(s->block); s->block = parse_hsize_list(opt_arg); break; + default: goto end_collect; + } + } while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF); + +end_collect: + last_was_dset = FALSE; + + if (opt != EOF) + goto parse_start; + else + goto parse_end; + } + /** end subsetting parameters **/ + + case 'h': + usage(progname); + exit(EXIT_SUCCESS); + case '?': + default: + usage(progname); + exit(EXIT_FAILURE); + } + } + +parse_end: + return hand; +} + + +/*------------------------------------------------------------------------- + * Function: free_handler + * + * Purpose: Convenience function to free the handler_t structures. Needs a + * length variable (LEN) to know how many in the array it needs + * to free + * + * Return: Nothing + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +free_handler(struct handler_t *hand, int len) +{ + register int i; + + for (i = 0; i < len; i++) { + free(hand[i].obj); + + if (hand[i].subset_info) { + free(hand[i].subset_info->start); + free(hand[i].subset_info->stride); + free(hand[i].subset_info->count); + free(hand[i].subset_info->block); + free(hand[i].subset_info); + } + } + + free(hand); +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 dumper + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Albert Cheng + * 30. September 2000 + * Add the -o option--output file for datasets raw data + * + * REMcG + * November 2000 + * Changes to support XML. + * + * Bill Wendling + * Wednesday, 10. January 2001 + * Modified the way command line parameters are interpreted. They go + * through one function call now (get_option). + * + * Bill Wendling + * Tuesday, 20. February 2001 + * Moved command line parsing to separate function. Made various + * "display_*" flags global. + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + hid_t fid, gid; + const char *fname = NULL; + void *edata; + hid_t (*func)(void*); + find_objs_t info; + struct handler_t *hand; + int i; + + if (argc < 2) { + usage(progname); + exit(EXIT_FAILURE); + } + + dump_header_format = &standardformat; + dump_function_table = &ddl_function_table; + + /* Disable error reporting */ + H5Eget_auto(&func, &edata); + H5Eset_auto(NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + hand = parse_command_line(argc, argv); + + /* Check for conflicting options */ + if (doxml) { + if (!display_all) { + error_msg(progname, "option \"%s\" not available for XML\n", + "to display selected objects"); + exit(EXIT_FAILURE); + } else if (display_bb) { + error_msg(progname, "option \"%s\" not available for XML\n", + "--boot-block"); + exit(EXIT_FAILURE); + } else if (!display_data) { + error_msg(progname, "option \"%s\" not available for XML\n", + "--header"); + exit(EXIT_FAILURE); + } else if (display_oid == 1) { + error_msg(progname, "option \"%s\" not available for XML\n", + "--object-ids"); + exit(EXIT_FAILURE); + } else if (usingdasho) { + error_msg(progname, "option \"%s\" not available for XML\n", + "--output"); + exit(EXIT_FAILURE); + } + } else { + if (xml_dtd_uri) { + warn_msg(progname, "option \"%s\" only applies with XML: %s\n", + "--xml-dtd", xml_dtd_uri); + } + } + + if (argv[opt_ind][0] == '\\') + fname = &argv[opt_ind][1]; + else + fname = argv[opt_ind]; + + fid = h5dump_fopen(fname, NULL, 0); + + if (fid < 0) { + error_msg(progname, "unable to open file \"%s\"\n", fname); + exit(EXIT_FAILURE); + } + + /* allocate and initialize internal data structure */ + init_table(&group_table); + init_table(&type_table); + init_table(&dset_table); + init_prefix(&prefix, prefix_len); + + /* init the find_objs_t */ + info.threshold = 0; + info.prefix_len = prefix_len; + info.prefix = calloc((size_t)info.prefix_len, 1); + info.group_table = group_table; + info.type_table = type_table; + info.dset_table = dset_table; + info.status = d_status; + + if (doxml) { + /* initialize XML */ + thefile = fid; + + /* find all objects that might be targets of a refernce */ + if ((gid = H5Gopen(fid, "/")) < 0) { + error_msg(progname, "unable to open root group\n"); + d_status = EXIT_FAILURE; + goto done; + } + + ref_path_table_put(gid, "/"); + H5Giterate(fid, "/", NULL, fill_ref_path_table, NULL); + H5Gclose(gid); + + /* reset prefix! */ + strcpy(prefix, ""); + + /* make sure the URI is initialized to something */ + if (xml_dtd_uri == NULL) + xml_dtd_uri = DEFAULT_DTD; + } + + /* find all shared objects */ + H5Giterate(fid, "/", NULL, find_objs, (void *)&info); + + /* does there exist unamed committed data type */ + for (i = 0; i < type_table->nobjs; i++) + if (type_table->objs[i].recorded == 0) + unamedtype = 1; + + dump_tables(); + + if (info.status) { + error_msg(progname, "internal error (file %s:line %d)\n", + __FILE__, __LINE__); + d_status = EXIT_FAILURE; + goto done; + } + + /* start to dump */ + if (!doxml) { + begin_obj(dump_header_format->filebegin, fname, + dump_header_format->fileblockbegin); + } else { + printf("\n"); + printf("\n", + xml_dtd_uri); + printf("\n"); + } + + if (display_bb) + dump_bb(); + + if (display_all) { + if ((gid = H5Gopen(fid, "/")) < 0) { + error_msg(progname, "unable to open root group\n"); + d_status = EXIT_FAILURE; + } else { + dump_function_table->dump_group_function(gid, "/"); + } + + if (H5Gclose(gid) < 0) { + error_msg(progname, "unable to close root group\n"); + d_status = EXIT_FAILURE; + } + } else { + if (doxml) { + /* Note: this option is not supported for XML */ + error_msg(progname, "internal error (file %s:line %d)\n", + __FILE__, __LINE__); + d_status = EXIT_FAILURE; + goto done; + } + + for (i = 0; i < argc; i++) + if (hand[i].func) + hand[i].func(fid, hand[i].obj, hand[i].subset_info); + } + + if (!doxml) { + end_obj(dump_header_format->fileend, + dump_header_format->fileblockend); + } else { + printf("%s\n", dump_header_format->fileend); + } + +done: + if (H5Fclose(fid) < 0) + d_status = EXIT_FAILURE; + + free_handler(hand, argc); + + free(group_table->objs); + free(dset_table->objs); + free(type_table->objs); + free(prefix); + free(info.prefix); + + /* To Do: clean up XML table */ + + h5tools_close(); + H5Eset_auto(func, edata); + return d_status; +} + +/*------------------------------------------------------------------------- + * Function: print_enum + * + * Purpose: prints the enum data - + * + * Return: void + * + * Programmer: Patrick Lu + * + * Modifications: + * + * NOTE: this function was taken from h5ls. should be moved into the toolslib + * + *-----------------------------------------------------------------------*/ +static void +print_enum(hid_t type) +{ + char **name = NULL; /*member names */ + unsigned char *value = NULL; /*value array */ + int nmembs; /*number of members */ + int nchars; /*number of output characters */ + hid_t super; /*enum base integer type */ + hid_t native = -1; /*native integer data type */ + size_t dst_size; /*destination value type size */ + int i; + + nmembs = H5Tget_nmembers(type); + super = H5Tget_super(type); + + /* + * Determine what data type to use for the native values. To simplify + * things we entertain three possibilities: + * 1. long_long -- the largest native signed integer + * 2. unsigned long_long -- the largest native unsigned integer + * 3. raw format + */ + if (H5Tget_size(type) <= sizeof(long_long)) { + dst_size = sizeof(long_long); + + if (H5T_SGN_NONE == H5Tget_sign(type)) { + native = H5T_NATIVE_ULLONG; + } else { + native = H5T_NATIVE_LLONG; + } + } else { + dst_size = H5Tget_size(type); + } + + /* Get the names and raw values of all members */ + assert(nmembs>0); + name = calloc((size_t)nmembs, sizeof(char *)); + value = calloc((size_t)nmembs, MAX(H5Tget_size(type), dst_size)); + + for (i = 0; i < nmembs; i++) { + name[i] = H5Tget_member_name(type, i); + H5Tget_member_value(type, i, value + i * H5Tget_size(type)); + } + + /* Convert values to native data type */ + if (native > 0) + H5Tconvert(super, native, (hsize_t)nmembs, value, NULL, H5P_DEFAULT); + + /* + * Sort members by increasing value + * ***not implemented yet*** + */ + + /* Print members */ + for (i = 0; i < nmembs; i++) { + indentation(indent + COL); + nchars = printf("\"%s\"", name[i]); + printf("%*s ", MAX(0, 16 - nchars), ""); + + if (native < 0) { + size_t j; + + printf("0x"); + + for (j = 0; j < dst_size; j++) + printf("%02x", value[i * dst_size + j]); + } else if (H5T_SGN_NONE == H5Tget_sign(native)) { + printf("%" PRINTF_LL_WIDTH "u", *((unsigned long_long *) + ((void *) (value + i * dst_size)))); + } else { + printf("%" PRINTF_LL_WIDTH "d", + *((long_long *) ((void *) (value + i * dst_size)))); + } + + printf(";\n"); + } + + /* Release resources */ + for (i = 0; i < nmembs; i++) + free(name[i]); + + free(name); + free(value); + H5Tclose(super); + + if (0 == nmembs) + printf("\n%*s ", indent + 4, ""); +} + +/* + * XML support + */ + +/* + * XML needs a table to look up a path name for an object + * reference. + * + * This table stores mappings of reference -> path + * for all objects in the file that may be the target of + * an object reference. + * + * The 'path' is an absolute path by which the object + * can be accessed. When an object has > 1 such path, + * only one will be used in the table, with no particular + * method of selecting which one. + */ + +struct ref_path_table_entry_t { + hsize_t obj; + hobj_ref_t *obj_ref; + char *apath; + struct ref_path_table_entry_t *next; +}; + +struct ref_path_table_entry_t *ref_path_table = NULL; /* the table */ +int npte = 0; /* number of entries in the table */ + +/*------------------------------------------------------------------------- + * Function: ref_path_table_lookup + * + * Purpose: Looks up a table entry given a path name. + * Used during construction of the table. + * + * Return: The table entre (pte) or NULL if not in the + * table. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static struct ref_path_table_entry_t * +ref_path_table_lookup(const char *thepath) +{ + int i; + hobj_ref_t *ref; + herr_t status; + struct ref_path_table_entry_t *pte = ref_path_table; + + if (ref_path_table == NULL) + return NULL; + + ref = (hobj_ref_t *) malloc(sizeof(hobj_ref_t)); + + if (ref == NULL) { + /* fatal error ? */ + return NULL; + } + + status = H5Rcreate(ref, thefile, thepath, H5R_OBJECT, -1); + + if (status < 0) { + /* fatal error ? */ + return NULL; + } + + for (i = 0; i < npte; i++) { + if (memcmp(ref, pte->obj_ref, sizeof(hobj_ref_t)) == 0) { + return pte; + } + + pte = pte->next; + } + + return NULL; +} + +/*------------------------------------------------------------------------- + * Function: ref_path_table_put + * + * Purpose: Enter the 'obj' with 'path' in the table if + * not already there. + * Create an object reference, pte, and store them + * in the table. + * + * Return: The object reference for the object. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hobj_ref_t * +ref_path_table_put(hid_t obj, const char *path) +{ + hobj_ref_t *ref; + herr_t status; + struct ref_path_table_entry_t *pte; + + /* look up 'obj'. If already in table, return */ + pte = ref_path_table_lookup(path); + if (pte != NULL) + return pte->obj_ref; + + /* if not found, then make new entry */ + + pte = (struct ref_path_table_entry_t *) + malloc(sizeof(struct ref_path_table_entry_t)); + if (pte == NULL) { + /* fatal error? */ + return NULL; + } + + pte->obj = obj; + ref = (hobj_ref_t *) malloc(sizeof(hobj_ref_t)); + if (ref == NULL) { + /* fatal error? */ + free(pte); + return NULL; + } + + status = H5Rcreate(ref, thefile, path, H5R_OBJECT, -1); + if (status < 0) { + /* fatal error? */ + free(ref); + free(pte); + return NULL; + } + + pte->obj_ref = ref; + + pte->apath = strdup(path); + + pte->next = ref_path_table; + ref_path_table = pte; + + npte++; + + return ref; +} + +/*------------------------------------------------------------------------- + * Function: lookup_ref_path + * + * Purpose: Lookup the path to the object with refernce 'ref'. + * + * Return: Return a path to the object, or NULL if not found. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +lookup_ref_path(hobj_ref_t * ref) +{ + int i; + struct ref_path_table_entry_t *pte = NULL; + + if (ref_path_table == NULL) + return NULL; + + pte = ref_path_table; + if (pte == NULL) { + /* fatal -- not initialized? */ + return NULL; + } + for (i = 0; i < npte; i++) { + if (memcmp(ref, pte->obj_ref, sizeof(hobj_ref_t)) == 0) { + return pte->apath; + } + pte = pte->next; + } + return NULL; +} + +/*------------------------------------------------------------------------- + * Function: fill_ref_path_table + * + * Purpose: Called by interator to create references for + * all objects and enter them in the table. + * + * Return: Error status. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +fill_ref_path_table(hid_t group, const char *name, void UNUSED * op_data) +{ + hid_t obj; + char *tmp; + H5G_stat_t statbuf; + struct ref_path_table_entry_t *pte; + char *thepath; + + H5Gget_objinfo(group, name, FALSE, &statbuf); + tmp = (char *) malloc(strlen(prefix) + strlen(name) + 2); + + if (tmp == NULL) + return FAIL; + + thepath = (char *) malloc(strlen(prefix) + strlen(name) + 2); + + if (thepath == NULL) { + free(tmp); + return FAIL; + } + + strcpy(tmp, prefix); + + strcpy(thepath, prefix); + strcat(thepath, "/"); + strcat(thepath, name); + + switch (statbuf.type) { + case H5G_DATASET: + if ((obj = H5Dopen(group, name)) >= 0) { + pte = ref_path_table_lookup(thepath); + if (pte == NULL) { + ref_path_table_put(obj, thepath); + } + H5Dclose(obj); + } else { + error_msg(progname, "unable to get dataset \"%s\"\n", name); + d_status = EXIT_FAILURE; + } + break; + case H5G_GROUP: + if ((obj = H5Gopen(group, name)) >= 0) { + strcat(strcat(prefix, "/"), name); + pte = ref_path_table_lookup(thepath); + if (pte == NULL) { + ref_path_table_put(obj, thepath); + H5Giterate(obj, ".", NULL, fill_ref_path_table, NULL); + strcpy(prefix, tmp); + } + H5Gclose(obj); + } else { + error_msg(progname, "unable to dump group \"%s\"\n", name); + d_status = EXIT_FAILURE; + } + break; + case H5G_TYPE: + if ((obj = H5Topen(group, name)) >= 0) { + pte = ref_path_table_lookup(thepath); + if (pte == NULL) { + ref_path_table_put(obj, thepath); + } + H5Tclose(obj); + } else { + error_msg(progname, "unable to get dataset \"%s\"\n", name); + d_status = EXIT_FAILURE; + } + break; + default:; + } + + free(tmp); + free(thepath); + return 0; +} + +static const char *quote = """; +static const char *amp = "&"; +static const char *lt = "<"; +static const char *gt = ">"; +static const char *apos = "'"; + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_name + * + * Purpose: Escape XML reserved chars in a name, so HDF5 strings + * and paths can be correctly read back in XML element. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_name(const char *str) +{ + int extra; + int len; + int i; + const char *cp; + char *ncp; + char *rcp; + + if (!str) + return NULL; + + cp = str; + len = strlen(str); + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\"') { + extra += (strlen(quote) - 1); + } else if (*cp == '\'') { + extra += (strlen(apos) - 1); + } else if (*cp == '<') { + extra += (strlen(lt) - 1); + } else if (*cp == '>') { + extra += (strlen(gt) - 1); + } else if (*cp == '&') { + extra += (strlen(amp) - 1); + } + + cp++; + } + + if (extra == 0) + return strdup(str); + + cp = str; + rcp = ncp = calloc((size_t)(len + extra + 1), sizeof(char)); + + if (!ncp) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + if (*cp == '\'') { + strncpy(ncp, apos, strlen(apos)); + ncp += strlen(apos); + cp++; + } else if (*cp == '<') { + strncpy(ncp, lt, strlen(lt)); + ncp += strlen(lt); + cp++; + } else if (*cp == '>') { + strncpy(ncp, gt, strlen(gt)); + ncp += strlen(gt); + cp++; + } else if (*cp == '\"') { + strncpy(ncp, quote, strlen(quote)); + ncp += strlen(quote); + cp++; + } else if (*cp == '&') { + strncpy(ncp, amp, strlen(amp)); + ncp += strlen(amp); + cp++; + } else { + *ncp++ = *cp++; + } + } + + *ncp = '\0'; + return rcp; +} + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_string + * + * Purpose: Escape XML reserved chars in a string, so HDF5 strings + * and paths can be correctly read back in XML CDATA. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_string(const char *str, int slen) +{ + int extra; + int len; + int i; + const char *cp; + char *ncp; + char *rcp; + + if (!str) + return NULL; + + cp = str; + + if (slen < 0) + len = strlen(str); + else + len = slen; + + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\\') { + extra++; + } else if (*cp == '\"') { + extra++; + } else if (*cp == '\'') { + extra += (strlen(apos) - 1); + } else if (*cp == '<') { + extra += (strlen(lt) - 1); + } else if (*cp == '>') { + extra += (strlen(gt) - 1); + } else if (*cp == '&') { + extra += (strlen(amp) - 1); + } + cp++; + } + + cp = str; + rcp = ncp = calloc((size_t)(len + extra + 1), sizeof(char)); + + if (ncp == NULL) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + if (*cp == '\\') { + *ncp++ = '\\'; + *ncp++ = *cp++; + } else if (*cp == '\"') { + *ncp++ = '\\'; + *ncp++ = *cp++; + } else if (*cp == '\'') { + strncpy(ncp, apos, strlen(apos)); + ncp += strlen(apos); + cp++; + } else if (*cp == '<') { + strncpy(ncp, lt, strlen(lt)); + ncp += strlen(lt); + cp++; + } else if (*cp == '>') { + strncpy(ncp, gt, strlen(gt)); + ncp += strlen(gt); + cp++; + } else if (*cp == '&') { + strncpy(ncp, amp, strlen(amp)); + ncp += strlen(amp); + cp++; + } else { + *ncp++ = *cp++; + } + } + + *ncp = '\0'; + return rcp; +} + +/** + ** XML print functions--these replace some functions in the + ** h5tools.c suite. + **/ + +/*------------------------------------------------------------------------- + * Function: xml_print_datatype + * + * Purpose: Print description of a datatype in XML. + * Note: this is called inside a element. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_datatype(hid_t type) +{ + char *fname; + hid_t nmembers, mtype; + int i, j, ndims, perm[H5DUMP_MAX_RANK]; + size_t size; + hsize_t dims[H5DUMP_MAX_RANK]; + H5T_str_t str_pad; + H5T_cset_t cset; + H5G_stat_t statbuf; + hid_t super; + H5T_order_t ord; + H5T_sign_t sgn; + size_t sz; + size_t spos; + size_t epos; + size_t esize; + size_t mpos; + size_t msize; + int nmembs; + + switch (H5Tget_class(type)) { + case H5T_INTEGER: + indentation(indent); + printf("\n"); + indent += COL; + /* */ + ord = H5Tget_order(type); + sgn = H5Tget_sign(type); + indentation(indent); + printf("\n"); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_FLOAT: + /* */ + ord = H5Tget_order(type); + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n", + msize, mpos); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_TIME: + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n"); + printf(""); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_STRING: + /* */ + size = H5Tget_size(type); + str_pad = H5Tget_strpad(type); + cset = H5Tget_cset(type); + + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n"); + } else if (str_pad == H5T_STR_NULLPAD) { + printf("H5T_STR_NULLPAD\"/>\n"); + } else if (str_pad == H5T_STR_SPACEPAD) { + printf("H5T_STR_SPACEPAD\"/>\n"); + } else { + printf("H5T_STR_ERROR\"/>\n"); + } + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_BITFIELD: + /* */ + ord = H5Tget_order(type); + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n", size); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_OPAQUE: + /* */ + + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n", size); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_COMPOUND: + /* recursively describe the components of a compound datatype */ + if (H5Tcommitted(type) > 0) { + /* detect a shared datatype, output only once */ + H5Gget_objinfo(type, ".", TRUE, &statbuf); + i = search_obj(type_table, statbuf.objno); + + if (i >= 0) { + /* This should be defined somewhere else */ + if (!type_table->objs[i].recorded) { + /* 'anonymous' NDT. Use it's object num. + as it's name. */ + printf("\n", + type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + } else { + /* point to the NDT by name */ + char *t_objname = xml_escape_the_name(type_table->objs[i].objname); + + printf("\n", t_objname); + free(t_objname); + } + } else { + printf("\n"); + d_status = EXIT_FAILURE; + } + + } else { + /* type of a dataset */ + nmembers = H5Tget_nmembers(type); + + indentation(indent); + printf("\n"); + + /* List each member Field of the type */ + /* */ + /* */ + indent += COL; + for (i = 0; i < nmembers; i++) { + char *t_fname; + + fname = H5Tget_member_name(type, i); + mtype = H5Tget_member_type(type, i); + indentation(indent); + t_fname = xml_escape_the_name(fname); + printf("\n", t_fname); + + free(fname); + free(t_fname); + indent += COL; + indentation(indent); + printf("\n"); + indent += COL; + xml_print_datatype(mtype); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + + indentation(indent); + printf("\n"); + } + indent -= COL; + indentation(indent); + printf("\n"); + } + break; + + case H5T_REFERENCE: + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + /* Only Object references supported at this time */ + printf("\n"); + indentation(indent + COL); + printf("\n"); + indentation(indent); + printf("\n"); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_ENUM: + /* + list Name, values of enum + */ + nmembs = H5Tget_nmembers(type); + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n", nmembs); + xml_print_enum(type); + indentation(indent); + printf("\n"); + indent -= COL; + indentation(indent); + printf("\n"); + break; + + case H5T_VLEN: + indentation(indent); + printf("\n"); + super = H5Tget_super(type); + indent += COL; + indentation(indent); + printf("\n"); + indent += COL; + xml_print_datatype(super); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + indentation(indent); + printf("\n"); + H5Tclose(super); + + break; + + case H5T_ARRAY: + /* Get array base type */ + super = H5Tget_super(type); + + /* Print lead-in */ + indentation(indent); + printf("\n", ndims); + + /* Get array information */ + H5Tget_array_dims(type, dims, perm); + + /* list of dimensions */ + indent += COL; + if (perm != NULL) { + /* for each dimension, list */ + for (j = 0; j < ndims; j++) { + indentation(indent); + printf("\n", + (int) dims[j], (int) perm[j]); + } + } else { + for (j = 0; j < ndims; j++) { + indentation(indent); + printf("\n", + (int) dims[j]); + } + } + indent -= COL; + + indent += COL; + indentation(indent); + printf("\n"); + indent += COL; + xml_print_datatype(super); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + indentation(indent); + printf("\n"); + /* Close array base type */ + H5Tclose(super); + break; + + default: + printf(""); + d_status = EXIT_FAILURE; + break; + } +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_datatype + * + * Purpose: Dump description of a datatype in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_datatype(hid_t type) +{ + int i; + H5G_stat_t statbuf; + + indent += COL; + indentation(indent); + + if (H5Tcommitted(type) > 0) { + /* Data type is a shared or named data type */ + H5Gget_objinfo(type, ".", TRUE, &statbuf); + i = search_obj(type_table, statbuf.objno); + + if (i >= 0) { + /* Shared data type, must be entered as an object */ + if (!type_table->objs[i].recorded) { + /* anonymous stored data type: + following the dumper's current + practice: + use it's object ref as its name + */ + printf("\n", + type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + } else { + /* pointer to a named data type already in XML */ + char *t_objname = xml_escape_the_name(type_table->objs[i].objname); + + printf("\n", t_objname); + free(t_objname); + } + } else { + printf("\n"); + } + indent -= COL; + return; + } + printf("%s %s\n", dump_header_format->datatypebegin, + dump_header_format->datatypeblockbegin); + indent += COL; + xml_print_datatype(type); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_dataspace + * + * Purpose: Dump description of a dataspace in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_dataspace(hid_t space) +{ + hsize_t size[H5DUMP_MAX_RANK]; + hsize_t maxsize[H5DUMP_MAX_RANK]; + int ndims = + H5Sget_simple_extent_dims(space, size, maxsize); + int i; + + indentation(indent + COL); + printf("%s\n", dump_header_format->dataspacebegin); + if (H5Sis_simple(space)) { + indentation(indent + COL + COL); + + if (ndims == 0) { + /* scalar dataspace (just a tag, no XML attrs. defined */ + printf("\n"); + } else { + /* simple dataspace */ + /* */ + printf("\n", ndims); + + /* print the elements */ + for (i = 0; i < ndims; i++) { + indentation(indent + COL + COL + COL); + if (maxsize[i] == H5S_UNLIMITED) { + HDfprintf(stdout, + "\n", + size[i]); + } else if (maxsize[i] == (hsize_t) 0) { + HDfprintf(stdout, + "\n", + size[i], size[i]); + } else { + HDfprintf(stdout, + "\n", + size[i], maxsize[i]); + } + } + indentation(indent + COL + COL); + printf("\n"); + } + } else { + printf("\n"); + } + + indentation(indent + COL); + printf("%s\n", dump_header_format->dataspaceend); + +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_data + * + * Purpose: Dump description of data in XML. + * Note that this calls the h5dump_xxx calls in + * the h5tools library. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_data(hid_t obj_id, int obj_data) +{ + h5dump_t *outputformat = &xml_dataformat; + int status = -1; + void *buf; + hid_t space, type, p_type; + int ndims, i; + hsize_t size[64], nelmts = 1; + int depth; + int stdindent = COL; /* should be 3 */ + + outputformat->line_ncols = nCols; + indent += COL; + + /* + * the depth will tell us how far we need to indent extra. we use to just + * use indent but with the merging of the tools lib we have to do + * something different for the lib funtions... the normal indentation is 6 + * so when we don't need any extra indentation, depth will be 0. + */ + depth = indent / stdindent + 1; + + /* Print all the values. */ + indentation(indent); + printf("%s\n", dump_header_format->databegin); + indentation(indent + COL); + printf("\n"); + if (obj_data == DATASET_DATA) { + type = H5Dget_type(obj_id); + if (H5Tget_class(type) == H5T_REFERENCE) { + status = xml_print_refs(obj_id, DATASET_DATA); + } else if (H5Tget_class(type) == H5T_STRING) { + status = xml_print_strs(obj_id, DATASET_DATA); + } else { + status = h5dump_dset(stdout, outputformat, obj_id, -1, depth); + } + } else { + /* Attribute data */ + type = H5Aget_type(obj_id); + + if (H5Tget_class(type) == H5T_REFERENCE) { + /* references are done differently than + the standard output: + XML dumps a path to the object + referenced. + */ + status = xml_print_refs(obj_id, ATTRIBUTE_DATA); + H5Tclose(type); + } else if (H5Tget_class(type) == H5T_STRING) { + status = xml_print_strs(obj_id, ATTRIBUTE_DATA); + } else { + /* all other data */ + p_type = h5dump_fixtype(type); + H5Tclose(type); + + space = H5Aget_space(obj_id); + + ndims = H5Sget_simple_extent_dims(space, size, NULL); + + for (i = 0; i < ndims; i++) + nelmts *= size[i]; + + buf = + malloc((size_t)(nelmts * MAX(H5Tget_size(type), H5Tget_size(p_type)))); + assert(buf); + + if (H5Aread(obj_id, p_type, buf) >= 0) { + status = + h5dump_mem(stdout, outputformat, obj_id, p_type, space, + buf, depth); + } + free(buf); + H5Tclose(p_type); + H5Sclose(space); + H5Tclose(type); + } + } + + if (status < 0) { + indentation(indent + COL); + printf("Unable to print data.\n"); + status = 1; + } + + indentation(indent + COL); + printf("\n"); + indentation(indent); + printf("%s\n", dump_header_format->dataend); + indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_attr + * + * Purpose: Dump a description of an HDF5 attribute in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +xml_dump_attr(hid_t attr, const char *attr_name, void UNUSED * op_data) +{ + hid_t attr_id, type, space; + char *t_aname = xml_escape_the_name(attr_name); + + indentation(indent); + printf("\n", t_aname); + free(t_aname); + + if ((attr_id = H5Aopen_name(attr, attr_name)) >= 0) { + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + if (display_data) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA); + break; + + case H5T_TIME: + indent += COL; + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indent -= COL; + break; + + case H5T_COMPOUND: + indentation(indent); + printf("\n"); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA); + break; + + case H5T_REFERENCE: + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + xml_print_refs(attr_id, ATTRIBUTE_DATA); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + break; + + case H5T_VLEN: + printf("\n"); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA); + break; + default: + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n", H5Tget_class(type)); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + break; + } + } else { + /* The case of an attribute never yet written ?? */ + indentation(indent); + printf("\n"); + indentation(indent + COL); + printf("\n"); + indentation(indent); + printf("\n"); + } + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr_id); + indentation(indent); + printf("%s\n", dump_header_format->attributeend); + return SUCCEED; + + } else { + /* ?? failed */ + indentation(indent + COL); + printf("\n"); + indentation(indent); + printf("%s\n", dump_header_format->attributeend); + d_status = EXIT_FAILURE; + return FAIL; + } +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_named_datatype + * + * Purpose: Dump a description of an HDF5 NDT in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_named_datatype(hid_t type, const char *name) +{ + int nmembers = 1, x; + hid_t mtype; + char *fname; + char *tmp; + + tmp = malloc(strlen(prefix) + strlen(name) + 2); + strcpy(tmp, prefix); + strcat(tmp, "/"); + strcat(tmp, name); + + indentation(indent); + if (strncmp(name, "#", 1) == 0) { + /* Special: this is an 'anonymous' NDT, deleted but + still in use. + We follow the dumper's undocumented practice, and + use its object id as its name. + Exactly the same as normal, but a separate case + in the event we want to do something else in + the future. + */ + char *t_tmp = xml_escape_the_name(tmp); + char *t_prefix = xml_escape_the_name(prefix); + + printf("\n", + name, t_tmp, (strcmp(prefix, "") ? t_prefix : "root")); + free(t_tmp); + free(t_prefix); + } else { + char *t_name = xml_escape_the_name(name); + char *t_prefix = xml_escape_the_name(prefix); + char *t_tmp = xml_escape_the_name(tmp); + + printf("\n", + t_name, t_tmp, (strcmp(prefix, "") ? t_prefix : "root")); + + free(t_name); + free(t_prefix); + free(t_tmp); + } + + indent += COL; + + if (H5Tget_class(type) == H5T_COMPOUND) { + /* Dump this here for sure. */ + nmembers = H5Tget_nmembers(type); + + indentation(indent); + printf("\n"); + + indent += COL; + for (x = 0; x < nmembers; x++) { + char *t_fname; + + fname = H5Tget_member_name(type, x); + mtype = H5Tget_member_type(type, x); + indentation(indent); + t_fname = xml_escape_the_name(fname); + printf("\n", t_fname); + free(fname); + free(t_fname); + + if ((H5Tget_class(mtype) == H5T_COMPOUND) + || (H5Tget_class(mtype) == H5T_VLEN) + || (H5Tget_class(mtype) == H5T_ARRAY)) { + indent += COL; + + /* Nested compound type: recur */ + indentation(indent); + printf("%s %s\n", dump_header_format->datatypebegin, + dump_header_format->datatypeblockbegin); + indent += COL; + xml_print_datatype(mtype); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + } else { + indent += COL; + indentation(indent); + printf("%s %s\n", dump_header_format->datatypebegin, + dump_header_format->datatypeblockbegin); + indent += COL; + xml_print_datatype(mtype); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + } + + indentation(indent); + printf("\n"); + } + + indent -= COL; + indentation(indent); + printf("\n"); + } else { + /* Other data types: call print_datatype */ + indent += COL; + xml_print_datatype(type); + indent -= COL; + } + + indent -= COL; + indentation(indent); + printf("\n"); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_group + * + * Purpose: Dump a description of an HDF5 Group (and its members) in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_group(hid_t gid, const char *name) +{ + H5G_stat_t statbuf; + char *cp; + hid_t dset, type; + char typename[1024], *tmp; + char *par; + int i; + int isRoot = 0; + int xtype; + + if (strcmp(name, "/") == 0) { + isRoot = 1; + } else { + tmp = malloc(strlen(prefix) + strlen(name) + 2); + strcpy(tmp, prefix); + par = strdup(tmp); + cp = strrchr(par, '/'); + if (cp != NULL) { + if ((cp == par) && strlen(par) > 1) { + *(cp + 1) = '\0'; + } else { + *cp = '\0'; + } + } + } + + indentation(indent); + + if (isRoot) { + printf("\n"); + } else { + char *t_name = xml_escape_the_name(name); + char *t_tmp = xml_escape_the_name(tmp); + char *t_par = xml_escape_the_name(par); + + printf("\n", + t_name, t_tmp, (strcmp(prefix, "") ? t_par : "root")); + free(t_name); + free(t_tmp); + free(t_par); + } + + indent += COL; + H5Gget_objinfo(gid, ".", TRUE, &statbuf); + + if (statbuf.nlink > 1) { + /* Group with more than one link to it... */ + i = search_obj(group_table, statbuf.objno); + + if (i < 0) { + indentation(indent); + error_msg(progname, "internal error (file %s:line %d)\n", + __FILE__, __LINE__); + d_status = EXIT_FAILURE; + } else if (group_table->objs[i].displayed) { + /* already seen: enter a groupptr */ + char *t_objname = xml_escape_the_name(group_table->objs[i].objname); + + indentation(indent + COL); + printf("\n", t_objname); + free(t_objname); + } else { + /* first time this group has been seen -- describe it */ + strcpy(group_table->objs[i].objname, prefix); + group_table->objs[i].displayed = 1; + + /* 1. do all the attributes of the group */ + H5Aiterate(gid, NULL, + dump_function_table->dump_attribute_function, NULL); + + if (!strcmp(name, "/") && unamedtype) { + /* Very special case: dump unamed type in root group */ + for (i = 0; i < type_table->nobjs; i++) { + if (!type_table->objs[i].recorded) { + dset = H5Dopen(gid, type_table->objs[i].objname); + type = H5Dget_type(dset); + sprintf(typename, "#%lu:%lu", + type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + dump_function_table->dump_named_datatype_function(type, typename); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the members */ + xtype = H5G_TYPE; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_DATASET; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_LINK; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_GROUP; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + } + } else { + /* 1. do all the attributes of the group */ + H5Aiterate(gid, NULL, dump_function_table->dump_attribute_function, + NULL); + + if (!strcmp(name, "/") && unamedtype) { + /* Very special case: dump unamed type in root group */ + for (i = 0; i < type_table->nobjs; i++) { + if (!type_table->objs[i].recorded) { + dset = H5Dopen(gid, type_table->objs[i].objname); + type = H5Dget_type(dset); + sprintf(typename, "#%lu:%lu", + type_table->objs[i].objno[0], + type_table->objs[i].objno[1]); + dump_function_table->dump_named_datatype_function(type, typename); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the members */ + xtype = H5G_TYPE; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_DATASET; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_LINK; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + xtype = H5G_GROUP; + H5Giterate(gid, ".", NULL, dump_all, (void *) &xtype); + } + + indent -= COL; + indentation(indent); + if (isRoot) { + printf("\n"); + } else { + printf("%s\n", dump_header_format->groupend); + } +/* don't free this!!! + free(tmp); +*/ +} + +/*------------------------------------------------------------------------- + * Function: xml_print_refs + * + * Purpose: Print a path to the objects referenced by HDF5 Referneces. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_refs(hid_t did, int source) +{ + herr_t e; + hid_t type, space; + char *buf; + hobj_ref_t *refbuf; + char *path; + hsize_t ssiz; + hsize_t i; + + if (source == DATASET_DATA) { + type = H5Dget_type(did); + } else if (source == ATTRIBUTE_DATA) { + type = H5Aget_type(did); + } else { + /* return an error */ + return FAIL; + } + if (H5Tget_class(type) != H5T_REFERENCE) { + /* return an error */ + return FAIL; + } + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + /* region ref not supported yet... */ + /* return an error */ + return FAIL; + } + if (source == DATASET_DATA) { + space = H5Dget_space(did); + ssiz = H5Sget_simple_extent_npoints(space); + ssiz *= H5Tget_size(type); + + buf = calloc((size_t)ssiz, sizeof(char)); + if (buf == NULL) { + return FAIL; + } + e = H5Dread(did, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + /* need to check result here */ + if (e < 0) { + free(buf); + return FAIL; + } + + } else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + ssiz = H5Sget_simple_extent_npoints(space); + ssiz *= H5Tget_size(type); + + buf = calloc((size_t)ssiz, sizeof(char)); + if (buf == NULL) { + free(buf); + return FAIL; + } + e = H5Aread(did, H5T_STD_REF_OBJ, buf); + /* need to check the result here */ + } else { + /* error */ + return FAIL; + } + + refbuf = (hobj_ref_t *) buf; + ssiz = H5Sget_simple_extent_npoints(space); + + for (i = 0; i < ssiz; i++) { + path = lookup_ref_path(refbuf); + indentation(indent + COL); + + if (!path) { + printf("\"%s\"\n", "NULL"); + } else { + char *t_path = xml_escape_the_string(path, -1); + + printf("\"%s\"\n", t_path); + free(t_path); + } + + refbuf++; + } + + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: xml_print_strs + * + * Purpose: Print strings. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_strs(hid_t did, int source) +{ + herr_t e; + hid_t type, space; + char *buf; + char *bp; + char *onestring; + hsize_t ssiz; + size_t tsiz; + size_t i; + if (source == DATASET_DATA) { + type = H5Dget_type(did); + } else if (source == ATTRIBUTE_DATA) { + type = H5Aget_type(did); + } else { + /* return an error */ + return FAIL; + } + if (H5Tget_class(type) != H5T_STRING) { + /* return an error */ + return FAIL; + } + if (source == DATASET_DATA) { + space = H5Dget_space(did); + ssiz = H5Sget_simple_extent_npoints(space); + ssiz *= H5Tget_size(type); + + buf = calloc((size_t)ssiz, sizeof(char)); + if (buf == NULL) { + return FAIL; + } + e = H5Dread(did, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + if (e < 0) { + free(buf); + return FAIL; + } + + } else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + ssiz = H5Sget_simple_extent_npoints(space); + ssiz *= H5Tget_size(type); + + buf = calloc((size_t)ssiz, sizeof(char)); + if (buf == NULL) { + return FAIL; + } + e = H5Aread(did, type, buf); + if (e < 0) { + free(buf); + return FAIL; + } + } else { + /* error */ + return FAIL; + } + +/* pull out each string... */ + ssiz = H5Sget_simple_extent_npoints(space); + + tsiz = H5Tget_size(type); + onestring = (char *) calloc((size_t)tsiz, sizeof(char)); + bp = buf; + + for (i = 0; i < ssiz; i++) { + strncpy(onestring, bp, tsiz); + indentation(indent + COL); + + if (!onestring) { + printf("\"%s\"\n", "NULL"); + } else { + char *t_onestring = xml_escape_the_string(onestring, (int)tsiz); + + printf("\"%s\"\n", xml_escape_the_string(onestring, (int)tsiz)); + free(t_onestring); + } + + bp += tsiz; + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: check_compression + * + * Purpose: private function to check for compression and + * put a comment in the XML. (Not fully implemented.) + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +check_compression(hid_t dcpl) +{ + int nfilt; + int i; + H5Z_filter_t filter; + char namebuf[20]; + size_t cd_nelmts = 1; + unsigned int cd_values; + unsigned int flags; +/* not used yet: will need to do somehting more elaborate to handle future + * compression methods. + char *t1 = "H5Z_FILTER_DEFLATE"; +*/ + + nfilt = H5Pget_nfilters(dcpl); + if (nfilt <= 0) + return; + for (i = 0; i < nfilt; i++) { + filter = H5Pget_filter(dcpl, i, &flags, + (size_t *) &cd_nelmts, + &cd_values, 20, namebuf); + if (filter == H5Z_FILTER_DEFLATE) { + indentation(indent + COL); + printf("\n"); + indentation(indent + COL); + printf("\n", cd_values); + } + } +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_group + * + * Purpose: Dump a description of an HDF5 Group (and its members) in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_dump_dataset(hid_t did, const char *name) +{ + hid_t type, space; + hid_t dcpl; + int maxdims; + hsize_t *chsize; + int ndims; + int i; + char *tmp; + char *t_name, *t_tmp, *t_prefix; + + tmp = malloc(strlen(prefix) + strlen(name) + 2); + strcpy(tmp, prefix); + strcat(tmp, "/"); + strcat(tmp, name); + indentation(indent); + + t_name = xml_escape_the_name(name); + t_tmp = xml_escape_the_name(tmp); + t_prefix = xml_escape_the_name(prefix); + + printf("\n", + t_name, t_tmp, (strcmp(prefix, "") ? t_prefix : "root")); + + free(t_name); + free(t_tmp); + free(t_prefix); + + dcpl = H5Dget_create_plist(did); + type = H5Dget_type(did); + space = H5Dget_space(did); + + /* Print information about chunked storage */ + if (H5D_CHUNKED == H5Pget_layout(dcpl)) { + maxdims = H5Sget_simple_extent_ndims(space); + chsize = (hsize_t *) malloc(maxdims * sizeof(hsize_t)); + indent += COL; + indentation(indent); + printf("\n"); + indent += COL; + indentation(indent); + printf("\n", ndims); + /* check for compression and tell about it... */ + + check_compression(dcpl); + + indent += COL; + + for (i = 0; i < ndims; i++) { + indentation(indent); + HDfprintf(stdout, "\n", chsize[i]); + } + + indent -= COL; + + indentation(indent); + printf("\n"); + indent -= COL; + indentation(indent); + printf("\n"); + indent -= COL; + free(chsize); + } + /* and check for external.... */ + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + indent += COL; + H5Aiterate(did, NULL, dump_function_table->dump_attribute_function, NULL); + indent -= COL; + i = H5Dget_storage_size(did); + + if (display_data && (i > 0)) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + dump_function_table->dump_data_function(did, DATASET_DATA); + break; + + case H5T_TIME: + indent += COL; + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indent -= COL; + break; + + case H5T_COMPOUND: + indentation(indent); + printf("\n"); + dump_function_table->dump_data_function(did, DATASET_DATA); + break; + + case H5T_REFERENCE: + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + xml_print_refs(did, DATASET_DATA); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + break; + + case H5T_VLEN: + printf("\n"); + dump_function_table->dump_data_function(did, DATASET_DATA); + break; + default: + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n", H5Tget_class(type)); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + break; + } + } else { + /* no data written */ + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + } + +/* + free(tmp); +*/ + H5Tclose(type); + H5Sclose(space); + indentation(indent); + printf("%s\n", dump_header_format->datasetend); +} + +/*------------------------------------------------------------------------- + * Function: xml_print_enum + * + * Purpose: Print the values of an HDF5 ENUM in XML. + * Very similar to regular DDL output. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_enum(hid_t type) +{ + char **name = NULL; /*member names */ + unsigned char *value = NULL; /*value array */ + int nmembs; /*number of members */ + hid_t super; /*enum base integer type */ + hid_t native = -1; /*native integer data type */ + size_t dst_size; /*destination value type size */ + int i; /*miscellaneous counters */ + size_t j; + + nmembs = H5Tget_nmembers(type); + super = H5Tget_super(type); + + /* + * Determine what data type to use for the native values. To simplify + * things we entertain three possibilities: + * 1. long_long -- the largest native signed integer + * 2. unsigned long_long -- the largest native unsigned integer + * 3. raw format + */ + if (H5Tget_size(type) <= sizeof(long_long)) { + dst_size = sizeof(long_long); + + if (H5T_SGN_NONE == H5Tget_sign(type)) { + native = H5T_NATIVE_ULLONG; + } else { + native = H5T_NATIVE_LLONG; + } + } else { + dst_size = H5Tget_size(type); + } + + /* Get the names and raw values of all members */ + name = calloc((size_t)nmembs, sizeof(char *)); + value = calloc((size_t)nmembs, MAX(H5Tget_size(type), dst_size)); + + for (i = 0; i < nmembs; i++) { + name[i] = H5Tget_member_name(type, i); + H5Tget_member_value(type, i, value + i * H5Tget_size(type)); + } + + /* Convert values to native data type */ + if (native > 0) + H5Tconvert(super, native, (hsize_t)nmembs, value, NULL, H5P_DEFAULT); + + /* Sort members by increasing value */ + /*not implemented yet */ + + /* Print members */ + indent += COL; + for (i = 0; i < nmembs; i++) { + char *t_name = xml_escape_the_name(name[i]); + + indentation(indent); + printf("\n"); + indentation(indent + COL); + printf("%s\n", t_name); + free(t_name); + indentation(indent); + printf("\n"); + indentation(indent); + printf("\n"); + indentation(indent + COL); + if (native < 0) { + printf("0x"); + + for (j = 0; j < dst_size; j++) + printf("%02x", value[i * dst_size + j]); + } else if (H5T_SGN_NONE == H5Tget_sign(native)) { + printf("%" PRINTF_LL_WIDTH "u", *((unsigned long_long *) + ((void *) (value + i * dst_size)))); + } else { + printf("%" PRINTF_LL_WIDTH "d", + *((long_long *) ((void *) (value + i * dst_size)))); + } + printf("\n"); + indentation(indent); + printf("\n"); + + } + indent -= COL; + + /* Release resources */ + for (i = 0; i < nmembs; i++) + free(name[i]); + + free(name); + free(value); + H5Tclose(super); +} diff --git a/tools/h5dump/h5dump.h b/tools/h5dump/h5dump.h new file mode 100644 index 0000000..70c4178 --- /dev/null +++ b/tools/h5dump/h5dump.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 1998-2001 National Center for Supercomputing Applications + * All rights reserved. + * + */ +#ifndef H5DUMP_H__ +#define H5DUMP_H__ + +#include "hdf5.h" + +#define H5DUMP_MAX_RANK H5S_MAX_RANK + +#define begin_obj(obj,name,begin) \ + if (name) \ + printf("%s \"%s\" %s\n", (obj), (name), (begin)); \ + else \ + printf("%s %s\n", (obj), (begin)); + +#define end_obj(obj,end) \ + printf("%s %s\n", (end), (obj)); + +#endif /* !H5DUMP_H__ */ diff --git a/tools/h5dump/h5dumptst.c b/tools/h5dump/h5dumptst.c new file mode 100644 index 0000000..4e01627 --- /dev/null +++ b/tools/h5dump/h5dumptst.c @@ -0,0 +1,2577 @@ +/* + * Generate the binary hdf5 files for the h5dump tests. + * Usage: just execute the program without any arguments will + * generate all the binary hdf5 files in the local directory. + * + * If you regenerate the test files (e.g., changing some code, + * trying it on a new platform, ...), you need to verify the correctness + * of the expected output and update the corresponding *.ddl files. + */ +#include +#include "hdf5.h" +#include + +#define FILE1 "tgroup.h5" +#define FILE2 "tdset.h5" +#define FILE3 "tattr.h5" +#define FILE4 "tslink.h5" +#define FILE5 "thlink.h5" +#define FILE6 "tcompound.h5" +#define FILE7 "tall.h5" +#define FILE8 "tdset2.h5" +#define FILE9 "tcompound2.h5" +#define FILE10 "tloop.h5" +#define FILE11 "tloop2.h5" +#define FILE12 "tmany.h5" +#define FILE13 "tstr.h5" +#define FILE14 "tstr2.h5" +#define FILE15 "tenum.h5" +#define FILE16 "tobjref.h5" +#define FILE17 "tdatareg.h5" +#define FILE18 "tnestedcomp.h5" +#define FILE19 "topaque.h5" +#define FILE20 "tbitfields.h5" +#define FILE21 "tvldtypes1.h5" +#define FILE22 "tvldtypes2.h5" +#define FILE23 "tvldtypes3.h5" +#define FILE24 "tvldtypes4.h5" +#define FILE25 "tarray1.h5" +#define FILE26 "tarray2.h5" +#define FILE27 "tarray3.h5" +#define FILE28 "tarray4.h5" +#define FILE29 "tarray5.h5" +#define FILE30 "tarray6.h5" +#define FILE31 "tarray7.h5" +#define FILE32 "tempty.h5" + +#define LENSTR 50 +#define LENSTR2 11 + +#define SPACE2_RANK 2 +#define SPACE2_DIM1 10 +#define SPACE2_DIM2 10 + +#define SPACE1_RANK 1 +#define SPACE1_DIM1 4 + +/* Element selection information */ +#define POINT1_NPOINTS 10 + +typedef enum{ + RED, + GREEN, + BLUE, + WHITE, + BLACK +} enumtype; + +/* Compound datatype */ +typedef struct s1_t { + unsigned int a; + unsigned int b; + float c; +} s1_t; + + +/* 1-D array datatype */ +#define ARRAY1_RANK 1 +#define ARRAY1_DIM1 4 + +/* 3-D array datatype */ +#define ARRAY2_RANK 3 +#define ARRAY2_DIM1 3 +#define ARRAY2_DIM2 4 +#define ARRAY2_DIM3 5 + +/* 2-D array datatype */ +#define ARRAY3_RANK 2 +#define ARRAY3_DIM1 6 +#define ARRAY3_DIM2 3 + +static void test_group(void) +{ + hid_t fid, group; + + fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* / */ + group = H5Gcreate (fid, "/g1", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g2", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g3", 0); + H5Gclose(group); + + /* /g1 */ + group = H5Gcreate (fid, "/g1/g1.1", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g1/g1.2", 0); + H5Gclose(group); + + /* /g2 */ + group = H5Gcreate (fid, "/g2/g2.1", 0); + H5Gclose(group); + + /* /g3 */ + group = H5Gcreate (fid, "/g3/g3.1", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g3/g3.2", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g3/g3.3", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g3/g3.4", 0); + H5Gclose(group); + + /* /g2/g2.1 */ + group = H5Gcreate (fid, "/g2/g2.1/g2.1.1", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g2/g2.1/g2.1.2", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g2/g2.1/g2.1.3", 0); + H5Gclose(group); + + H5Fclose(fid); +} + +static void test_dataset(void) +{ + hid_t fid, dataset, space; + hsize_t dims[2]; + int dset1[10][20]; + double dset2[30][20]; + int i, j; + + fid = H5Fcreate(FILE2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* dset1 */ + dims[0] = 10; dims[1] = 20; + space = H5Screate_simple(2, dims, NULL); + dataset = H5Dcreate(fid, "/dset1", H5T_STD_I32BE, space, H5P_DEFAULT); + + for (i = 0; i < 10; i++) + for (j = 0; j < 20; j++) + dset1[i][j] = j+i; + + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + H5Sclose(space); + H5Dclose(dataset); + + /* dset2 */ + dims[0] = 30; dims[1] = 20; + space = H5Screate_simple(2, dims, NULL); + dataset = H5Dcreate(fid, "/dset2", H5T_IEEE_F64BE, space, H5P_DEFAULT); + + for (i = 0; i < 30; i++) + for (j = 0; j < 20; j++) + dset2[i][j] = 0.0001*j+i; + + H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + + H5Sclose(space); + H5Dclose(dataset); + H5Fclose(fid); +} + +static void test_dataset2(void) +{ + hid_t fid, dataset, space, create_plist; + hsize_t dims[2]; + hsize_t maxdims[2]; + int dset1[10][20]; + double dset2[30][10]; + int i, j; + + fid = H5Fcreate(FILE8, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + create_plist = H5Pcreate(H5P_DATASET_CREATE); + dims[0] = 5; dims[1] = 5; + H5Pset_chunk(create_plist, 2, dims); + + /* dset1 */ + dims[0] = 10; dims[1] = 20; + maxdims[0] = H5S_UNLIMITED; maxdims[1] = 20; + space = H5Screate_simple(2, dims, maxdims); + dataset = H5Dcreate(fid, "/dset1", H5T_STD_I32BE, space, create_plist); + + for (i = 0; i < 10; i++) + for (j = 0; j < 20; j++) + dset1[i][j] = j; + + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + H5Sclose(space); + H5Dclose(dataset); + + /* dset2 */ + dims[0] = 30; dims[1] = 10; + maxdims[0] = 30; maxdims[1] = H5S_UNLIMITED; + space = H5Screate_simple(2, dims, maxdims); + dataset = H5Dcreate(fid, "/dset2", H5T_IEEE_F64BE, space, create_plist); + + for (i = 0; i < 30; i++) + for (j = 0; j < 10; j++) + dset2[i][j] = j; + + H5Dwrite(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + + H5Sclose(space); + H5Dclose(dataset); + H5Fclose(fid); +} + + +static void test_attribute(void) +{ + hid_t fid, root, space, attr, type; + hsize_t dims[2]; + char buf[60]; + int i, data[10]; + double d[10]; + char string[]= "string attribute"; + int point = 100; + + fid = H5Fcreate(FILE3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + root = H5Gopen (fid, "/"); + + /* attribute 1 */ + dims[0] = 24; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (root, "attr1", H5T_STD_I8BE, space, H5P_DEFAULT); + sprintf(buf, "attribute of root group"); + H5Awrite(attr, H5T_NATIVE_SCHAR, buf); + H5Sclose(space); + H5Aclose(attr); + + /* attribute 2 */ + dims[0] = 10; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (root, "attr2", H5T_STD_I32BE, space, H5P_DEFAULT); + + for (i = 0; i < 10; i++) data[i] = i+1; + + H5Awrite(attr, H5T_NATIVE_INT, data); + H5Sclose(space); + H5Aclose(attr); + + /* attribute 3 */ + dims[0] = 10; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (root, "attr3", H5T_IEEE_F64BE, space, H5P_DEFAULT); + + for (i = 0; i < 10; i++) d[i] = 0.1 * i; + + H5Awrite(attr, H5T_NATIVE_DOUBLE, d); + H5Sclose(space); + H5Aclose(attr); + + /* attribute 4 */ + space = H5Screate(H5S_SCALAR); + attr = H5Acreate (root, "attr4", H5T_STD_I32BE, space, H5P_DEFAULT); + H5Awrite(attr, H5T_NATIVE_INT, &point); + H5Sclose(space); + H5Aclose(attr); + + /* attribute 5 */ + space = H5Screate(H5S_SCALAR); + type = H5Tcopy(H5T_C_S1); + H5Tset_size(type, 17); + attr = H5Acreate (root, "attr5", type, space, H5P_DEFAULT); + H5Awrite(attr, type, string); + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr); + H5Gclose(root); + H5Fclose(fid); +} + +static void test_softlink(void) +{ + hid_t fid, root; + + fid = H5Fcreate(FILE4, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + root = H5Gopen (fid, "/"); + H5Glink (root, H5G_LINK_SOFT, "somevalue", "slink1"); + H5Glink (root, H5G_LINK_SOFT, "linkvalue", "slink2"); + + H5Gclose(root); + H5Fclose(fid); +} + +/* + / + + / | \ the dataset is hardlinked to three names + /dset1, /g1/dset2, and /g1/g1.1/dset3 + dset1 g1 g2 + /g2 and /g1/g1.1 are hardlinked to the same object. + / \ + dset2 g1.1 + | + dset3 +*/ + +static void test_hardlink(void) +{ + hid_t fid, group, dataset, space; + hsize_t dim = 5; + int i, dset[5]; + + fid = H5Fcreate(FILE5, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + space = H5Screate_simple(1, &dim, NULL); + dataset = H5Dcreate(fid, "/dset1", H5T_STD_I32BE, space, H5P_DEFAULT); + + for (i = 0; i < 5; i++) dset[i] = i; + + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset); + H5Sclose(space); + H5Dclose(dataset); + + group = H5Gcreate (fid, "/g1", 0); + H5Glink (group, H5G_LINK_HARD, "/dset1", "dset2"); + H5Gclose(group); + + group = H5Gcreate (fid, "/g2", 0); + H5Glink (group, H5G_LINK_HARD, "/dset1", "dset3"); + H5Gclose(group); + + group = H5Gopen(fid, "/g1"); + H5Glink (group, H5G_LINK_HARD, "/g2", "g1.1"); + H5Gclose(group); + H5Fclose(fid); +} + +/* + / + / | \ \ + dset1 group1 type1 type2 + | + dset2 + +*/ +static void test_compound_dt(void) { /* test compound data type */ + hid_t fid, group, dataset, space, space3, type, type2; + hid_t array_dt; + typedef struct { + int a; + float b; + double c; + } dset1_t; + dset1_t dset1[5]; + + typedef struct { + int a; + float b; + } dset2_t; + dset2_t dset2[5]; + + typedef struct { + int a[4]; + float b[5][6]; + } dset3_t; + dset3_t dset3[3][6]; + + typedef struct { + int a; + float b; + } dset4_t; + dset4_t dset4[5]; + + typedef struct { + int a; + float b; + } dset5_t; + dset5_t dset5[5]; + + int i, j, k, l, ndims; + hsize_t dim[2]; + + hsize_t sdim = 5; + hsize_t dset3_dim[2]; + + + for (i = 0; i < (int)sdim; i++) { + dset1[i].a = i; + dset1[i].b = i*i; + dset1[i].c = 1./(i+1); + + dset2[i].a = i; + dset2[i].b = i+ i*0.1; + + dset4[i].a = i; + dset4[i].b = i+3; + + dset5[i].a = i; + dset5[i].b = i*0.1; + } + + + fid = H5Fcreate(FILE6, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + space = H5Screate_simple(1, &sdim, NULL); + + type = H5Tcreate (H5T_COMPOUND, sizeof(dset1[0])); + type2 = H5Tcreate(H5T_COMPOUND, sizeof(dset1[0])); + H5Tinsert(type, "a_name", HOFFSET(dset1_t, a), H5T_STD_I32BE); + H5Tinsert(type, "b_name", HOFFSET(dset1_t, b), H5T_IEEE_F32BE); + H5Tinsert(type, "c_name", HOFFSET(dset1_t, c), H5T_IEEE_F64BE); + H5Tinsert(type2, "a_name", HOFFSET(dset1_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "b_name", HOFFSET(dset1_t, b), H5T_NATIVE_FLOAT); + H5Tinsert(type2, "c_name", HOFFSET(dset1_t, c), H5T_NATIVE_DOUBLE); + dataset = H5Dcreate(fid, "/dset1", type, space, H5P_DEFAULT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + H5Tclose(type2); + H5Tclose(type); + H5Dclose(dataset); + + /* shared data type 1 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset2_t)); + H5Tinsert(type, "int_name", HOFFSET(dset2_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float_name", HOFFSET(dset2_t, b), H5T_IEEE_F32BE); + H5Tcommit(fid, "type1", type); + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset2_t)); + H5Tinsert(type2, "int_name", HOFFSET(dset2_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float_name", HOFFSET(dset2_t, b), H5T_NATIVE_FLOAT); + group = H5Gcreate (fid, "/group1", 0); + + dataset = H5Dcreate(group, "dset2", type, space, H5P_DEFAULT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + H5Tclose(type2); + H5Tclose(type); + H5Dclose(dataset); + + + /* shared data type 2 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset3_t)); + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset3_t)); + + ndims = 1; dim[0] = 4; + + array_dt=H5Tarray_create(H5T_STD_I32BE,ndims,dim,NULL); + H5Tinsert(type, "int_array", HOFFSET(dset3_t, a), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_NATIVE_INT,ndims,dim,NULL); + H5Tinsert(type2, "int_array", HOFFSET(dset3_t, a), array_dt); + H5Tclose(array_dt); + + ndims = 2; dim[0] = 5; dim[1] = 6; + + array_dt=H5Tarray_create(H5T_IEEE_F32BE,ndims,dim,NULL); + H5Tinsert(type, "float_array", HOFFSET(dset3_t, b), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_NATIVE_FLOAT,ndims,dim,NULL); + H5Tinsert(type2, "float_array", HOFFSET(dset3_t, b), array_dt); + H5Tclose(array_dt); + + H5Tcommit(fid, "type2", type); + + + dset3_dim[0] = 3; dset3_dim[1] = 6; + space3 = H5Screate_simple(2, dset3_dim, NULL); + dataset = H5Dcreate(group, "dset3", type, space3, H5P_DEFAULT); + for (i = 0; i < (int)dset3_dim[0]; i++) { + for (j = 0; j < (int)dset3_dim[1]; j++) { + for (k = 0; k < 4; k++) + dset3[i][j].a[k] = k+j+i; + for (k = 0; k < 5; k++) + for (l = 0; l < 6; l++) + dset3[i][j].b[k][l] = (k+1)+l+j+i; + } + } + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset3); + H5Sclose(space3); + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + + /* shared data type 3 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset4_t)); + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset4_t)); + H5Tinsert(type, "int", HOFFSET(dset4_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float", HOFFSET(dset4_t, b), H5T_IEEE_F32BE); + H5Tcommit(group, "type3", type); + H5Tinsert(type2, "int", HOFFSET(dset4_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float", HOFFSET(dset4_t, b), H5T_NATIVE_FLOAT); + dataset = H5Dcreate(group, "dset4", type, space, H5P_DEFAULT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset4); + + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + H5Gclose(group); + + + /* unamed data type */ + group = H5Gcreate (fid, "/group2", 0); + + type = H5Tcreate (H5T_COMPOUND, sizeof(dset5_t)); + H5Tinsert(type, "int", HOFFSET(dset5_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float", HOFFSET(dset5_t, b), H5T_IEEE_F32BE); + H5Tcommit(group, "type4", type); + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset5_t)); + H5Tinsert(type2, "int", HOFFSET(dset5_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float", HOFFSET(dset5_t, b), H5T_NATIVE_FLOAT); + dataset = H5Dcreate(group, "dset5", type, space, H5P_DEFAULT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset5); + + H5Gunlink(group,"type4"); + + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + H5Sclose(space); + H5Gclose(group); + + H5Fclose(fid); + +} + +/* + / + / | \ \ + dset1 group1 type1 type2 + | + dset2 + +*/ +static void test_compound_dt2(void) { /* test compound data type */ + hid_t fid, group, dataset, space, type, create_plist, type2; + hid_t array_dt; + + typedef struct { + int a; + float b; + double c; + } dset1_t; + dset1_t dset1[10]; + + typedef struct { + int a; + float b; + } dset2_t; + dset2_t dset2[10]; + + typedef struct { + int a[4]; + float b[5][6]; + } dset3_t; + + typedef struct { + int a; + float b; + } dset4_t; + dset4_t dset4[10]; + + typedef struct { + int a; + float b; + } dset5_t; + dset5_t dset5[10]; + + int i, ndims; + const int perm[2]={0,1}; + hsize_t dim[2]; + + hsize_t sdim, maxdim; + + sdim = 10; + for (i = 0; i < (int)sdim; i++) { + dset1[i].a = i; + dset1[i].b = i*i; + dset1[i].c = 1./(i+1); + + dset2[i].a = i; + dset2[i].b = i+ i*0.1; + + dset4[i].a = i; + dset4[i].b = i*1.0; + + dset5[i].a = i; + dset5[i].b = i*1.0; + } + + fid = H5Fcreate(FILE9, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + create_plist = H5Pcreate(H5P_DATASET_CREATE); + + sdim = 2; + H5Pset_chunk(create_plist, 1, &sdim); + + sdim = 6; + maxdim = H5S_UNLIMITED; + + space = H5Screate_simple(1, &sdim, &maxdim); + + type = H5Tcreate (H5T_COMPOUND, sizeof(dset1[0])); + + H5Tinsert(type, "a_name", HOFFSET(dset1_t, a), H5T_STD_I32BE); + H5Tinsert(type, "b_name", HOFFSET(dset1_t, b), H5T_IEEE_F32BE); + H5Tinsert(type, "c_name", HOFFSET(dset1_t, c), H5T_IEEE_F64BE); + + dataset = H5Dcreate(fid, "/dset1", type, space, create_plist); + + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset1[0])); + + H5Tinsert(type2, "a_name", HOFFSET(dset1_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "b_name", HOFFSET(dset1_t, b), H5T_NATIVE_FLOAT); + H5Tinsert(type2, "c_name", HOFFSET(dset1_t, c), H5T_NATIVE_DOUBLE); + + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + + H5Tclose(type); + H5Tclose(type2); + H5Sclose(space); + H5Dclose(dataset); + + sdim = 6; + maxdim = 10; + + space = H5Screate_simple(1, &sdim, &maxdim); + + /* shared data type 1 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset2_t)); + H5Tinsert(type, "int_name", HOFFSET(dset2_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float_name", HOFFSET(dset2_t, b), H5T_IEEE_F32BE); + H5Tcommit(fid, "type1", type); + + group = H5Gcreate (fid, "/group1", 0); + + dataset = H5Dcreate(group, "dset2", type, space, create_plist); + + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset2_t)); + H5Tinsert(type2, "int_name", HOFFSET(dset2_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float_name", HOFFSET(dset2_t, b), H5T_NATIVE_FLOAT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + + + /* shared data type 2 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset3_t)); + + ndims = 1; dim[0] = 4; + array_dt=H5Tarray_create(H5T_STD_I32BE,ndims,dim,perm); + H5Tinsert(type, "int_array", HOFFSET(dset3_t, a), array_dt); + H5Tclose(array_dt); + + ndims = 2; dim[0] = 5; dim[1] = 6; + array_dt=H5Tarray_create(H5T_IEEE_F32BE,ndims,dim,perm); + H5Tinsert(type, "float_array", HOFFSET(dset3_t, b), array_dt); + H5Tclose(array_dt); + + H5Tcommit(fid, "type2", type); + H5Tclose(type); + + /* shared data type 3 */ + type = H5Tcreate (H5T_COMPOUND, sizeof(dset4_t)); + H5Tinsert(type, "int", HOFFSET(dset4_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float", HOFFSET(dset4_t, b), H5T_IEEE_F32BE); + H5Tcommit(group, "type3", type); + + dataset = H5Dcreate(group, "dset4", type, space, create_plist); + + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset4_t)); + H5Tinsert(type2, "int", HOFFSET(dset4_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float", HOFFSET(dset4_t, b), H5T_NATIVE_FLOAT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset4); + + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + H5Gclose(group); + + + /* unamed data type */ + group = H5Gcreate (fid, "/group2", 0); + + type = H5Tcreate (H5T_COMPOUND, sizeof(dset5_t)); + H5Tinsert(type, "int", HOFFSET(dset5_t, a), H5T_STD_I32BE); + H5Tinsert(type, "float", HOFFSET(dset5_t, b), H5T_IEEE_F32BE); + H5Tcommit(group, "type4", type); + dataset = H5Dcreate(group, "dset5", type, space, create_plist); + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset5_t)); + H5Tinsert(type2, "int", HOFFSET(dset5_t, a), H5T_NATIVE_INT); + H5Tinsert(type2, "float", HOFFSET(dset5_t, b), H5T_NATIVE_FLOAT); + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset5); + + H5Gunlink(group,"type4"); + + H5Tclose(type); + H5Tclose(type2); + H5Dclose(dataset); + H5Sclose(space); + H5Gclose(group); + + H5Fclose(fid); + +} + + +/* + +/ : g1 g2 attr1 attr2 +g1 : g1.1 g1.2 +g1.1 : dset1.1.1(attr1, attr2) dset1.1.2 +g1.2 : g1.2.1 +g1.2.1 : slink +g2 : dset2.1 dset2.2 + +*/ + +static void test_all(void) { +hid_t fid, group, attr, dataset, space; +hsize_t dims[2]; +int data[2][2], dset1[10][10], dset2[20]; +char buf[60]; +int i, j; +float dset2_1[10], dset2_2[3][5]; + + fid = H5Fcreate(FILE7, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* create groups */ + group = H5Gcreate (fid, "/g1", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g2", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g1/g1.1", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g1/g1.2", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g1/g1.2/g1.2.1", 0); + H5Gclose(group); + + /* root attributes */ + group = H5Gopen (fid, "/"); + + dims[0] = 10; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (group, "attr1", H5T_STD_I8BE, space, H5P_DEFAULT); + sprintf(buf, "abcdefghi"); + H5Awrite(attr, H5T_NATIVE_SCHAR, buf); + H5Sclose(space); + H5Aclose(attr); + + dims[0] = 2; dims[1] = 2; + space = H5Screate_simple(2, dims, NULL); + attr = H5Acreate (group, "attr2", H5T_STD_I32BE, space, H5P_DEFAULT); + data[0][0] = 0; data[0][1] = 1; data[1][0] = 2; data[1][1] = 3; + H5Awrite(attr, H5T_NATIVE_INT, data); + H5Sclose(space); + H5Aclose(attr); + + H5Gclose(group); + + group = H5Gopen (fid, "/g1/g1.1"); + + /* dset1.1.1 */ + dims[0] = 10; dims[1] = 10; + space = H5Screate_simple(2, dims, NULL); + dataset = H5Dcreate(group, "dset1.1.1", H5T_STD_I32BE, space, H5P_DEFAULT); + for (i = 0; i < 10; i++) + for (j = 0; j < 10; j++) + dset1[i][j] = j*i; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + H5Sclose(space); + + /* attributes of dset1.1.1 */ + dims[0] = 27; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (dataset, "attr1", H5T_STD_I8BE, space, H5P_DEFAULT); + sprintf(buf, "1st attribute of dset1.1.1"); + H5Awrite(attr, H5T_NATIVE_SCHAR, buf); + H5Sclose(space); + H5Aclose(attr); + + dims[0] = 27; + space = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (dataset, "attr2", H5T_STD_I8BE, space, H5P_DEFAULT); + sprintf(buf, "2nd attribute of dset1.1.1"); + H5Awrite(attr, H5T_NATIVE_SCHAR, buf); + H5Sclose(space); + H5Aclose(attr); + + H5Dclose(dataset); + + /* dset1.1.2 */ + dims[0] = 20; + space = H5Screate_simple(1, dims, NULL); + dataset = H5Dcreate(group, "dset1.1.2", H5T_STD_I32BE, space, H5P_DEFAULT); + for (i = 0; i < 20; i++) + dset2[i] = i; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + H5Sclose(space); + H5Dclose(dataset); + + H5Gclose(group); + + /* soft link */ + group = H5Gopen (fid, "/g1/g1.2/g1.2.1"); + H5Glink (group, H5G_LINK_SOFT, "somevalue", "slink"); + H5Gclose(group); + + group = H5Gopen (fid, "/g2"); + + /* dset2.1 */ + dims[0] = 10; + space = H5Screate_simple(1, dims, NULL); + dataset = H5Dcreate(group, "dset2.1", H5T_IEEE_F32BE, space, H5P_DEFAULT); + for (i = 0; i < 10; i++) + dset2_1[i] = i*0.1+1; + H5Dwrite(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2_1); + H5Sclose(space); + H5Dclose(dataset); + + /* dset2.2 */ + dims[0] = 3; dims[1] = 5; + space = H5Screate_simple(2, dims, NULL); + dataset = H5Dcreate(group, "dset2.2", H5T_IEEE_F32BE, space, H5P_DEFAULT); + for (i = 0; i < 3; i++) + for (j = 0; j < 5; j++) + dset2_2[i][j] = (i+1)*j*0.1; + H5Dwrite(dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2_2); + H5Sclose(space); + H5Dclose(dataset); + + H5Gclose(group); + + H5Fclose(fid); + +} + +/* + o + /___\ + g1 o/ \o g2 + \___/ + + +o - group objects + +*/ + +static void test_loop(void) { +hid_t fid, group; + + fid = H5Fcreate(FILE10, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + group = H5Gcreate (fid, "/g1", 0); + H5Gclose(group); + group = H5Gcreate (fid, "/g2", 0); + H5Gclose(group); + + H5Glink(fid, H5G_LINK_HARD, "/g2", "/g1/g1.1"); + H5Glink(fid, H5G_LINK_HARD, "/g1", "/g2/g2.1"); + + H5Fclose(fid); +} + +static void test_loop2(void) { +hid_t fid, group; + + fid = H5Fcreate(FILE11, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* create group object g1 and implcit path from root object */ + group = H5Gcreate (fid, "/g1", 0); + H5Gclose(group); + + /* create group object g2 and implcit path from root object */ + group = H5Gcreate (fid, "/g2", 0); + H5Gclose(group); + + /* create path from object at /g1 to object at /g2 and name it g1.1 */ + H5Glink (fid, H5G_LINK_HARD, "/g2", "/g1/g1.1"); + + /* create path from object at /g2 to object at /g1 and name it g2.1 */ + H5Glink (fid, H5G_LINK_SOFT, "/g1", "/g2/g2.1"); + + H5Fclose(fid); + +} + +/* + / + | | | \ \ \ + g1 g2 g3 g4 g5 g6 + / \ | | \ \ \ + g1.1 g1.2 slink2 link3 dset2 slink4 dset3 + | | (g1) (dset2) (dset3) + dset1 link1 + (dset1) +*/ + +static void test_many(void) { + hid_t fid, group, attr, dataset, space, space2, type, create_plist, type2; + hid_t array_dt; + hsize_t dims[2]; + int data[2][2], dset2[10][10], dset3[10][10]; + double d[10]; + + char buf[60]; + int i, j; + int i0, i1, i2, i3; + hsize_t sdim, maxdim; + + typedef struct { /* compound type has members with rank > 1 */ + int a[2][2][2][2]; /* arrays are 2x2x2x2 */ + double b[2][2][2][2]; + double c[2][2][2][2]; + } dset1_t; + dset1_t dset1[6]; + + hsize_t dim[4]; + int index[4] = {0,1,2,3}; /* normal indicies */ + const int perm[4] = {0,1,2,3}; /* the 0'th and the 3'rd indices are permuted */ + + fid = H5Fcreate(FILE12, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + group = H5Gcreate (fid, "/g1", 0); + H5Gclose(group); + + create_plist = H5Pcreate(H5P_DATASET_CREATE); + + sdim = 2; + H5Pset_chunk(create_plist, 1, &sdim); + + group = H5Gcreate (fid, "/g1/g1.1", 0); + + type = H5Tcreate (H5T_COMPOUND, sizeof(dset1[0])); + + dim[0] = dim[1] = dim[2] = dim[3] = 2; + array_dt=H5Tarray_create(H5T_STD_I32BE,4,dim,perm); + H5Tinsert(type, "a_array", HOFFSET(dset1_t, a), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_IEEE_F64BE,4,dim,perm); + H5Tinsert(type, "b_array", HOFFSET(dset1_t, b), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_IEEE_F64BE,4,dim,perm); + H5Tinsert(type, "c_array", HOFFSET(dset1_t, c), array_dt); + H5Tclose(array_dt); + + type2 = H5Tcreate (H5T_COMPOUND, sizeof(dset1[0])); + + array_dt=H5Tarray_create(H5T_NATIVE_INT,4,dim,perm); + H5Tinsert(type2, "a_array", HOFFSET(dset1_t, a), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_NATIVE_DOUBLE,4,dim,perm); + H5Tinsert(type2, "b_array", HOFFSET(dset1_t, b), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_NATIVE_DOUBLE,4,dim,perm); + H5Tinsert(type2, "c_array", HOFFSET(dset1_t, c), array_dt); + H5Tclose(array_dt); + + + /* dset1 */ + sdim = 6; + maxdim = H5S_UNLIMITED; + space = H5Screate_simple(1, &sdim, &maxdim); + dataset = H5Dcreate(group, "dset1", type, space, create_plist); + + /* add attributes to dset1 */ + dims[0] = 10; + space2 = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (dataset, "attr1", H5T_STD_I8BE, space2, H5P_DEFAULT); + sprintf(buf, "abcdefghi"); + H5Awrite(attr, H5T_NATIVE_CHAR, buf); + H5Sclose(space2); + H5Aclose(attr); + + dims[0] = 2; dims[1] = 2; + space2 = H5Screate_simple(2, dims, NULL); + attr = H5Acreate (dataset, "attr2", H5T_STD_I32BE, space2, H5P_DEFAULT); + data[0][0] = 0; data[0][1] = 1; data[1][0] = 2; data[1][1] = 3; + H5Awrite(attr, H5T_NATIVE_INT, data); + H5Sclose(space2); + H5Aclose(attr); + + dims[0] = 10; + space2 = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (dataset, "attr3", H5T_IEEE_F64BE, space2, H5P_DEFAULT); + for (i = 0; i < 10; i++) d[i] = 0.1 * i; + H5Awrite(attr, H5T_NATIVE_DOUBLE, d); + H5Sclose(space2); + H5Aclose(attr); + + for (j=0; j<(int)sdim; j++) { + for (i3 = 0; i3 < 2; i3++) { + index[perm[3]] = i3; + for (i2 = 0; i2 < 2; i2++) { + index[perm[2]] = i2; + for (i1 = 0; i1 < 2; i1++) { + index[perm[1]] = i1; + for (i0 = 0; i0 < 2; i0++) { + index[perm[0]] = i0; + + dset1[j].a[index[3]][index[2]][index[1]][index[0]] = i0+j; + dset1[j].b[index[3]][index[2]][index[1]][index[0]] = (double)(i0+j); +#if WIN32 + dset1[j].c[index[3]][index[2]][index[1]][index[0]] = (double)(i0+j+(signed __int64)sdim); +#else + dset1[j].c[index[3]][index[2]][index[1]][index[0]] = (double)(i0+j+sdim); +#endif + } + } + } + } + } + + H5Dwrite(dataset, type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset1); + + H5Dclose(dataset); + H5Sclose(space); + + H5Tclose(type); + H5Tclose(type2); + H5Gclose(group); + + group = H5Gcreate (fid, "/g1/g1.2", 0); + H5Glink (group, H5G_LINK_HARD, "/g1/g1.1/dset1", "link1"); + H5Gclose(group); + + group = H5Gcreate (fid, "/g2", 0); + H5Glink (group, H5G_LINK_SOFT, "/g1", "slink2"); + H5Gclose(group); + + group = H5Gcreate (fid, "/g3", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g4", 0); + + /* dset2 */ + dims[0] = 10; dims[1] = 10; + space = H5Screate_simple(2, dims, NULL); + + dataset = H5Dcreate(group, "dset2", H5T_STD_I32BE, space, H5P_DEFAULT); + for (i = 0; i < 10; i++) + for (j = 0; j < 10; j++) + dset2[i][j] = j; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset2); + + H5Dclose(dataset); + + H5Sclose(space); + H5Gclose(group); + + group = H5Gopen(fid, "/g3"); + H5Glink (group, H5G_LINK_HARD, "/g4/dset2", "link3"); + H5Gclose(group); + + group = H5Gcreate (fid, "/g5", 0); + H5Gclose(group); + + group = H5Gcreate (fid, "/g6", 0); + /* dset3 */ + dims[0] = 10; dims[1] = 10; + space = H5Screate_simple(2, dims, NULL); + + dataset = H5Dcreate(group, "dset3", H5T_STD_I32BE, space, H5P_DEFAULT); + for (i = 0; i < 10; i++) + for (j = 0; j < 10; j++) + dset3[i][j] = i; + H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset3); + + H5Dclose(dataset); + + H5Sclose(space); + H5Gclose(group); + + group = H5Gopen(fid, "/g5"); + H5Glink (group, H5G_LINK_SOFT, "/g6/dset3", "slink4"); + H5Gclose(group); + + H5Fclose(fid); + +} +static hid_t mkstr(int size, H5T_str_t pad) { +hid_t type; + + if ((type=H5Tcopy(H5T_C_S1))<0) return -1; + if (H5Tset_size(type, (size_t)size)<0) return -1; + if (H5Tset_strpad(type, pad)<0) return -1; + + return type; +} + +static void test_str(void) { + hid_t fid, dataset, space, f_type, m_type, str_type, f_type2; + hid_t array_dt; + + hsize_t dims1[] = { 3, 4}; + char string1[12][2] = {"s1","s2","s3","s4","s5","s6","s7","s8","s9", + "s0","s1","s2"}; + + hsize_t dims2[]={20}; + char string2[20][9] = {"ab cd ef1", "ab cd ef2", "ab cd ef3", "ab cd ef4", + "ab cd ef5", "ab cd ef6", "ab cd ef7", "ab cd ef8", + "ab cd ef9", "ab cd ef0", "ab cd ef1", "ab cd ef2", + "ab cd ef3", "ab cd ef4", "ab cd ef5", "ab cd ef6", + "ab cd ef7", "ab cd ef8", "ab cd ef9", "ab cd ef0"}; + + hsize_t dims3[] = { 27}; + char string3[27][5] = {"abcd0", "abcd1", "abcd2", "abcd3", + "abcd4", "abcd5", "abcd6", "abcd7", + "abcd8", "abcd9", "abcd0", "abcd1", + "abcd2", "abcd3", "abcd4", "abcd5", + "abcd6", "abcd7", "abcd8", "abcd9", + "abcd0", "abcd1", "abcd2", "abcd3", + "abcd4", "abcd5", "abcd6"}; + + int i, j, k, l; + + hsize_t dims4[] = { 3 }; + char string4[3][20] = { "s1234567890123456789", "s1234567890123456789", + "s1234567890123456789"}; + + hsize_t dims5[] = { 3, 6}; + typedef struct { + int a[8][10]; + char s[12][32]; + } compound_t; + compound_t comp1[3][6]; + hsize_t mdims[2]; + + fid = H5Fcreate(FILE13, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* string 1 : nullterm string */ + space = H5Screate_simple(2, dims1, NULL); + f_type = mkstr(5, H5T_STR_NULLTERM); + m_type = mkstr(2, H5T_STR_NULLTERM); + dataset = H5Dcreate(fid, "/string1", f_type, space, H5P_DEFAULT); + H5Dwrite(dataset, m_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, string1); + H5Tclose(m_type); + H5Tclose(f_type); + H5Sclose(space); + H5Dclose(dataset); + + /* string 2 : space pad string */ + space = H5Screate_simple(1, dims2, NULL); + f_type = mkstr(11, H5T_STR_SPACEPAD); + m_type = mkstr(9, H5T_STR_NULLTERM); + dataset = H5Dcreate(fid, "/string2", f_type, space, H5P_DEFAULT); + H5Dwrite(dataset, m_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, string2); + H5Tclose(m_type); + H5Tclose(f_type); + H5Sclose(space); + H5Dclose(dataset); + + /* string 3 : null pad string */ + space = H5Screate_simple(1, dims3, NULL); + f_type = mkstr(8, H5T_STR_NULLPAD); + m_type = mkstr(5, H5T_STR_NULLTERM); + dataset = H5Dcreate(fid, "/string3", f_type, space, H5P_DEFAULT); + H5Dwrite(dataset, m_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, string3); + H5Tclose(m_type); + H5Tclose(f_type); + H5Sclose(space); + H5Dclose(dataset); + + /* string 4 : space pad long string */ + space = H5Screate_simple(1, dims4, NULL); + f_type = mkstr(168, H5T_STR_SPACEPAD); + m_type = mkstr(20, H5T_STR_NULLTERM); + dataset = H5Dcreate(fid, "/string4", f_type, space, H5P_DEFAULT); + H5Dwrite(dataset, m_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, string4); + H5Tclose(m_type); + H5Tclose(f_type); + H5Sclose(space); + H5Dclose(dataset); + + /* compound data */ + space = H5Screate_simple(2, dims5, NULL); + f_type = H5Tcreate (H5T_COMPOUND, sizeof(compound_t)); + f_type2 = H5Tcreate (H5T_COMPOUND, sizeof(compound_t)); + + mdims[0] = 8; mdims[1] = 10; + + array_dt=H5Tarray_create(H5T_STD_I32BE,2,mdims,NULL); + H5Tinsert(f_type, "int_array", HOFFSET(compound_t, a), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(H5T_NATIVE_INT,2,mdims,NULL); + H5Tinsert(f_type2, "int_array", HOFFSET(compound_t, a), array_dt); + H5Tclose(array_dt); + + str_type = mkstr(32, H5T_STR_SPACEPAD); + mdims[0] = 3; mdims[1] = 4; + + array_dt=H5Tarray_create(str_type,2,mdims,NULL); + H5Tinsert(f_type, "string", HOFFSET(compound_t, s), array_dt); + H5Tclose(array_dt); + + array_dt=H5Tarray_create(str_type,2,mdims,NULL); + H5Tinsert(f_type2, "string", HOFFSET(compound_t, s), array_dt); + H5Tclose(array_dt); + + for (i = 0; i < 3; i++) + for (j = 0; j < 6; j++) { + for (k = 0 ; k < 8; k++) + for (l = 0; l < 10; l++) + comp1[i][j].a[k][l] = (l+j+k) * (l+j+k); + for (k = 0 ; k < 12; k++) + sprintf(comp1[i][j].s[k], "abcdefgh12345678abcdefgh12345678"); + } + + dataset = H5Dcreate(fid, "/comp1", f_type, space, H5P_DEFAULT); + H5Dwrite(dataset, f_type2, H5S_ALL, H5S_ALL, H5P_DEFAULT, comp1); + + H5Tclose(str_type); + H5Tclose(f_type); + H5Tclose(f_type2); + H5Sclose(space); + H5Dclose(dataset); + + H5Fclose(fid); +} + +/* + / + / / | \ \ \ + g1 g2 g3 g4 g5 g6 + | | | | \ \ + string1 string3 string5 + string2 string4 string6 +*/ + +static void test_str2(void) +{ +hid_t fid, group, attr, dataset, space, space2, mem_space, hyper_space; +hid_t fxdlenstr, fxdlenstr2, memtype; +hsize_t dims[1], size[1], stride[1], count[1], block[1]; +hssize_t start[1]; + + +int i; +char buf[LENSTR+10]; +char buf2[3*LENSTR2]; +hsize_t sdim; + + fid = H5Fcreate(FILE14, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + fxdlenstr = H5Tcopy(H5T_C_S1); + H5Tset_size(fxdlenstr, LENSTR); + H5Tset_cset(fxdlenstr, H5T_CSET_ASCII); + H5Tset_strpad(fxdlenstr, H5T_STR_NULLTERM); + + memtype = H5Tcopy(H5T_C_S1); + H5Tset_size(memtype, LENSTR); + H5Tset_cset(memtype, H5T_CSET_ASCII); + H5Tset_strpad(memtype, H5T_STR_NULLTERM); + + sdim = 10; + size[0] = sdim; + space = H5Screate_simple(1, size, NULL); + size[0] = 1; + mem_space = H5Screate_simple(1,size,NULL); + hyper_space = H5Scopy(space); + + /* dset1 */ + + group = H5Gcreate (fid, "/g1", 0); + dataset = H5Dcreate(group, "dset1", fxdlenstr, space, H5P_DEFAULT); + + /* add attributes to dset1 */ + + fxdlenstr2 = H5Tcopy(H5T_C_S1); + H5Tset_size(fxdlenstr2, LENSTR2); + H5Tset_cset(fxdlenstr2, H5T_CSET_ASCII); + H5Tset_strpad(fxdlenstr2, H5T_STR_NULLTERM); + + dims[0] = 3; + space2 = H5Screate_simple(1, dims, NULL); + attr = H5Acreate (dataset, "attr1", fxdlenstr2, space2, H5P_DEFAULT); + sprintf(&(buf2[0*LENSTR2]), "0123456789"); + sprintf(&(buf2[1*LENSTR2]), "abcdefghij"); + sprintf(&(buf2[2*LENSTR2]), "ABCDEFGHIJ"); + H5Awrite(attr, fxdlenstr2, buf2); + H5Sclose(space2); + H5Tclose(fxdlenstr2); + H5Aclose(attr); + + stride[0]=1; + count[0]=1; + block[0]=1; + + for (i = 0; (hsize_t)i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_NULLTERM of",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + H5Dclose(dataset); + H5Gclose(group); + + group = H5Gcreate (fid, "/g2", 0); + dataset = H5Dcreate(group, "dset2", fxdlenstr, space, H5P_DEFAULT); + + for (i = 0; (hsize_t)i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_NULLTERM of string array",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + H5Dclose(dataset); + H5Gclose(group); + + + H5Tclose(fxdlenstr); + fxdlenstr = H5Tcopy(H5T_C_S1); + H5Tset_size(fxdlenstr, LENSTR); + H5Tset_cset(fxdlenstr, H5T_CSET_ASCII); + H5Tset_strpad(fxdlenstr, H5T_STR_NULLPAD); + + group = H5Gcreate (fid, "/g3", 0); + dataset = H5Dcreate(group, "dset3", fxdlenstr, space, H5P_DEFAULT); + + for (i = 0;(hsize_t) i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_NULLPAD of",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + H5Dclose(dataset); + H5Gclose(group); + + + group = H5Gcreate (fid, "/g4", 0); + dataset = H5Dcreate(group, "dset4", fxdlenstr, space, H5P_DEFAULT); + + for (i = 0; (hsize_t)i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_NULLPAD of string array",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + H5Dclose(dataset); + H5Gclose(group); + + H5Tclose(fxdlenstr); + fxdlenstr = H5Tcopy(H5T_C_S1); + H5Tset_size(fxdlenstr, LENSTR); + H5Tset_cset(fxdlenstr, H5T_CSET_ASCII); + H5Tset_strpad(fxdlenstr, H5T_STR_SPACEPAD); + + group = H5Gcreate (fid, "/g5", 0); + dataset = H5Dcreate(group, "dset5", fxdlenstr, space, H5P_DEFAULT); + + for (i = 0; (hsize_t)i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_SPACEPAD of",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + H5Dclose(dataset); + H5Gclose(group); + + + group = H5Gcreate (fid, "/g6", 0); + dataset = H5Dcreate(group, "dset6", fxdlenstr, space, H5P_DEFAULT); + + for (i = 0; (hsize_t)i < sdim; i++) { + start[0] = i; + sprintf(buf,"This is row %1d of type H5T_STR_SPACEPAD of string array",i); + H5Tset_size(memtype, HDstrlen(buf)+1); + H5Sselect_hyperslab(hyper_space, H5S_SELECT_SET, start, stride, count, block); + H5Dwrite(dataset, memtype, mem_space, hyper_space, H5P_DEFAULT, buf); + } + + H5Dclose(dataset); + H5Tclose(fxdlenstr); + H5Tclose(memtype); + H5Sclose(mem_space); + H5Sclose(hyper_space); + H5Sclose(space); + H5Fclose(fid); +} + +static void test_enum(void) +{ + /*some code is taken from enum.c in the test dir */ + hid_t file, type, space, dset; + int val; + enumtype data[] = {RED, GREEN, BLUE, GREEN, WHITE, + WHITE, BLACK, GREEN, BLUE, RED, + RED, BLUE, GREEN, BLACK, WHITE, + RED, WHITE, GREEN, GREEN, BLUE}; + hsize_t size[1] = {NELMTS(data)}; + + file = H5Fcreate(FILE15,H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + + type = H5Tcreate(H5T_ENUM, sizeof(enumtype)); + H5Tenum_insert(type, "RED", (val = 0, &val)); + H5Tenum_insert(type, "GREEN", (val = 1, &val)); + H5Tenum_insert(type, "BLUE", (val = 2, &val)); + H5Tenum_insert(type, "WHITE", (val = 3, &val)); + H5Tenum_insert(type, "BLACK", (val = 4, &val)); + H5Tcommit(file, "enum normal", type); + + space = H5Screate_simple(1,size,NULL); + dset = H5Dcreate(file,"table",type, space, H5P_DEFAULT); + H5Dwrite(dset,type,space,space,H5P_DEFAULT,data); + + H5Dclose(dset); + H5Sclose(space); + H5Fclose(file); +} + +static void test_objref(void) +{ +/*some code is taken from enum.c in the test dir */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + + hid_t group; /* Group ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Datatype ID */ + hsize_t dims1[] = {SPACE1_DIM1}; + hobj_ref_t *wbuf, /* buffer to write to disk */ + *rbuf, /* buffer read from disk */ + *tbuf; /* temp. buffer read from disk */ + uint32_t *tu32; /* Temporary pointer to uint32 data */ + intn i; /* counting variables */ + const char *write_comment="Foo!"; /* Comments for group */ + + /* Allocate write & read buffers */ + wbuf=malloc(sizeof(hobj_ref_t)*SPACE1_DIM1); + rbuf=malloc(sizeof(hobj_ref_t)*SPACE1_DIM1); + tbuf=malloc(sizeof(hobj_ref_t)*SPACE1_DIM1); + + /* Create file */ + fid1 = H5Fcreate(FILE16, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); + + /* Create a group */ + group=H5Gcreate(fid1,"Group1",(size_t)-1); + + /* Set group's comment */ + H5Gset_comment(group,".",write_comment); + + /* Create a dataset (inside Group1) */ + dataset=H5Dcreate(group,"Dataset1",H5T_STD_U32BE,sid1,H5P_DEFAULT); + + for(tu32=(uint32_t *)((void*)wbuf),i=0; ip=malloc((j+1)*sizeof(unsigned int)); + if(t1->p==NULL) { + printf("Cannot allocate memory for VL data! i=%u, j=%u\n",i,j); + return; + } /* end if */ + t1->len=j+1; + for(k=0; k<(j+1); k++) + ((unsigned int *)t1->p)[k]=i*100+j*10+k; + } /* end for */ + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE22, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); + + /* Create a VL datatype to refer to */ + tid1 = H5Tvlen_create (H5T_NATIVE_UINT); + + /* Create the base VL type */ + tid2 = H5Tvlen_create (tid1); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid2,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid2,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid2,sid1,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid2); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); + +} + +static void test_vldatatypes3(void) +{ + typedef struct { /* Struct that the VL sequences are composed of */ + int i; + float f; + hvl_t v; + } s1; + s1 wdata[SPACE1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1, tid2; /* Datatype IDs */ + hsize_t dims1[] = {SPACE1_DIM1}; + uintn i,j; /* counting variables */ + herr_t ret; /* Generic return value */ + + ret = ret; /* so that compiler won't complain "is set but never used" */ + + /* Allocate and initialize VL data to write */ + for(i=0; i$actual 2>&1 + + if $CMP $expect $actual; then + echo " PASSED" + else + echo "*FAILED*" + echo " Expected result (*.ddl) differs from actual result (*.out)" + nerrors="`expr $nerrors + 1`" + test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /' + fi + + # Clean up output file + if test -z "$HDF5_NOCLEANUP"; then + rm -f $actual + fi +} + +############################################################################## +############################################################################## +### T H E T E S T S ### +############################################################################## +############################################################################## + +# test for displaying groups +TOOLTEST tgroup-1.ddl tgroup.h5 +# test for displaying the selected groups +TOOLTEST tgroup-2.ddl --group=/g2 --group / -g /y tgroup.h5 + +# test for displaying simple space datasets +TOOLTEST tdset-1.ddl tdset.h5 +# test for displaying selected datasets +TOOLTEST tdset-2.ddl -H -d dset1 -d /dset2 --dataset=dset3 tdset.h5 + +# test for displaying attributes +TOOLTEST tattr-1.ddl tattr.h5 +# test for displaying the selected attributes of string type and scalar space +TOOLTEST tattr-2.ddl -a /attr1 --attribute /attr4 --attribute=/attr5 tattr.h5 +# test for header and error messages +TOOLTEST tattr-3.ddl --header -a /attr2 --attribute=/attr tattr.h5 + +# test for displaying soft links +TOOLTEST tslink-1.ddl tslink.h5 +# test for displaying the selected link +TOOLTEST tslink-2.ddl -l slink2 tslink.h5 + +# tests for hard links +TOOLTEST thlink-1.ddl thlink.h5 +TOOLTEST thlink-2.ddl -d /g1/dset2 --dataset /dset1 --dataset=/g1/g1.1/dset3 thlink.h5 +TOOLTEST thlink-3.ddl -d /g1/g1.1/dset3 --dataset /g1/dset2 --dataset=/dset1 thlink.h5 +TOOLTEST thlink-4.ddl -g /g1 thlink.h5 +TOOLTEST thlink-5.ddl -d /dset1 -g /g2 -d /g1/dset2 thlink.h5 + +# tests for compound data types +TOOLTEST tcomp-1.ddl tcompound.h5 +# test for named data types +TOOLTEST tcomp-2.ddl -t /type1 --datatype /type2 --datatype=/group1/type3 tcompound.h5 +# test for unamed type +TOOLTEST tcomp-3.ddl -t /#5992:0 -g /group2 tcompound.h5 + +#test for the nested compound type +TOOLTEST tnestcomp-1.ddl tnestedcomp.h5 + +# test for options +TOOLTEST tall-1.ddl tall.h5 +TOOLTEST tall-2.ddl --header -g /g1/g1.1 -a attr2 tall.h5 +TOOLTEST tall-3.ddl -d /g2/dset2.1 -l /g1/g1.2/g1.2.1/slink tall.h5 + +# test for loop detection +TOOLTEST tloop-1.ddl tloop.h5 + +# test for string +TOOLTEST tstr-1.ddl tstr.h5 +TOOLTEST tstr-2.ddl tstr2.h5 + +# test for file created by Lib SAF team +TOOLTEST tsaf.ddl tsaf.h5 + +# test for file with variable length data +TOOLTEST tvldtypes1.ddl tvldtypes1.h5 +TOOLTEST tvldtypes2.ddl tvldtypes2.h5 +TOOLTEST tvldtypes3.ddl tvldtypes3.h5 +TOOLTEST tvldtypes4.ddl tvldtypes4.h5 + +# test for files with array data +TOOLTEST tarray1.ddl tarray1.h5 +TOOLTEST tarray2.ddl tarray2.h5 +TOOLTEST tarray3.ddl tarray3.h5 +TOOLTEST tarray4.ddl tarray4.h5 +TOOLTEST tarray5.ddl tarray5.h5 +TOOLTEST tarray6.ddl tarray6.h5 +TOOLTEST tarray7.ddl tarray7.h5 + +# test for files with empty data +TOOLTEST tempty.ddl tempty.h5 + +# test XML +TOOLTEST tall.h5.xml --xml tall.h5 +TOOLTEST tattr.h5.xml --xml tattr.h5 +TOOLTEST tbitfields.h5.xml --xml tbitfields.h5 +TOOLTEST tcompound.h5.xml --xml tcompound.h5 +TOOLTEST tcompound2.h5.xml --xml tcompound2.h5 +TOOLTEST tdatareg.h5.xml --xml tdatareg.h5 +TOOLTEST tdset.h5.xml --xml tdset.h5 +TOOLTEST tdset2.h5.xml --xml tdset2.h5 +TOOLTEST tenum.h5.xml --xml tenum.h5 +TOOLTEST tgroup.h5.xml --xml tgroup.h5 +TOOLTEST thlink.h5.xml --xml thlink.h5 +TOOLTEST tloop.h5.xml --xml tloop.h5 +TOOLTEST tloop2.h5.xml --xml tloop2.h5 +TOOLTEST tmany.h5.xml --xml tmany.h5 +TOOLTEST tnestedcomp.h5.xml --xml tnestedcomp.h5 +TOOLTEST tobjref.h5.xml --xml tobjref.h5 +TOOLTEST topaque.h5.xml --xml topaque.h5 +TOOLTEST tslink.h5.xml --xml tslink.h5 +TOOLTEST tstr.h5.xml --xml tstr.h5 +TOOLTEST tstr2.h5.xml --xml tstr2.h5 +TOOLTEST tref.h5.xml --xml tref.h5 +TOOLTEST tname-amp.h5.xml --xml tname-amp.h5 +TOOLTEST tname-apos.h5.xml --xml tname-apos.h5 +TOOLTEST tname-gt.h5.xml --xml tname-gt.h5 +TOOLTEST tname-lt.h5.xml --xml tname-lt.h5 +TOOLTEST tname-quot.h5.xml --xml tname-quot.h5 +TOOLTEST tname-sp.h5.xml --xml tname-sp.h5 +TOOLTEST tstring.h5.xml --xml tstring.h5 +TOOLTEST tstring-at.h5.xml --xml tstring-at.h5 +TOOLTEST tref-escapes.h5.xml --xml tref-escapes.h5 +TOOLTEST tref-escapes-at.h5.xml --xml tref-escapes-at.h5 +TOOLTEST tnodata.h5.xml --xml tnodata.h5 +TOOLTEST tarray1.h5.xml --xml tarray1.h5 +TOOLTEST tarray2.h5.xml --xml tarray2.h5 +TOOLTEST tarray3.h5.xml --xml tarray3.h5 +TOOLTEST tarray6.h5.xml --xml tarray6.h5 +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 tsaf.h5.xml --xml tsaf.h5 +TOOLTEST tempty.h5.xml --xml tempty.h5 + +if test $nerrors -eq 0 ; then + echo "All $DUMPER tests passed." +fi + +exit $nerrors -- cgit v0.12