diff options
author | Bill Wendling <wendling@ncsa.uiuc.edu> | 2001-02-22 21:53:30 (GMT) |
---|---|---|
committer | Bill Wendling <wendling@ncsa.uiuc.edu> | 2001-02-22 21:53:30 (GMT) |
commit | 416a86e3ce3b967553003267a6e77c037e21815f (patch) | |
tree | 8f5ab1478acd23215c797b66730b784609c9c297 | |
parent | 20061988ec9daa96b5d5b9aaed75af587d582a0e (diff) | |
download | hdf5-416a86e3ce3b967553003267a6e77c037e21815f.zip hdf5-416a86e3ce3b967553003267a6e77c037e21815f.tar.gz hdf5-416a86e3ce3b967553003267a6e77c037e21815f.tar.bz2 |
[svn-r3488] Purpose:
Code Movement
Description:
Moved tools code into their own special subdirectories.
Platforms tested:
Linux, Kelgia
-rw-r--r-- | tools/h4toh5/Dependencies | 0 | ||||
-rw-r--r-- | tools/h4toh5/Makefile.in | 60 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5anno.c | 665 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5image.c | 861 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5main.c | 1629 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5main.h | 109 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5pal.c | 202 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5sds.c | 1096 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5test.c | 3944 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5util.c | 1633 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5util.h | 232 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5vdata.c | 831 | ||||
-rw-r--r-- | tools/h4toh5/h4toh5vgroup.c | 812 | ||||
-rwxr-xr-x | tools/h4toh5/testh4toh5.sh | 249 | ||||
-rw-r--r-- | tools/h5dump/Dependencies | 0 | ||||
-rw-r--r-- | tools/h5dump/Makefile.in | 65 | ||||
-rw-r--r-- | tools/h5dump/h5dump.c | 4680 | ||||
-rw-r--r-- | tools/h5dump/h5dump.h | 22 | ||||
-rw-r--r-- | tools/h5dump/h5dumptst.c | 2577 | ||||
-rwxr-xr-x | tools/h5dump/testh5dump.sh | 197 |
20 files changed, 19864 insertions, 0 deletions
diff --git a/tools/h4toh5/Dependencies b/tools/h4toh5/Dependencies new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/h4toh5/Dependencies 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<num_lab_anno;i++) { + ann_id = ANselect(an_id,i,AN_DATA_LABEL); + + 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)); + status = ANreadann(ann_id,ann_buf,ann_length+1); + if(status == FAIL) { + printf("error in reading data.\n"); + ANendaccess(ann_id); + ANend(an_id); + free(ann_buf); + return FAIL; + } + + status = ANendaccess(ann_id); + + h5_sid = H5Screate(H5S_SCALAR); + + if (h5_sid < 0) { + printf("failed to create attribute space for"); + printf(" HDF4 FILE ANNOTATION. \n"); + ANend(an_id); + free(lab_anno_list); + free(ann_buf); + return FAIL; + } + + if ((sh5str_type = mkstr(ann_length+1,H5T_STR_SPACEPAD))<0) { + printf("error in making string at OBJ LABEL. \n"); + ANend(an_id); + free(lab_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(lab_anno_list); + free(ann_buf); + return FAIL; + } + + /* obtain annotation object name. The name is defined based on object tag + */ + ann_obj_name = trans_tag_name(obj_tag,AN_DATA_LABEL); + + if(ann_obj_name != NULL) + strcpy(ann_labelname,ann_obj_name); + + strcat(ann_labelname,"_"); + strcat(ann_labelname,index_str); + + h5_aid = H5Acreate(h5group,ann_labelname,sh5str_type, + h5_sid,H5P_DEFAULT); + + if (h5_aid <0) { + + printf("failed to obtain attribute id for"); + printf(" file annotation. \n"); + ANend(an_id); + free(lab_anno_list); + free(ann_buf); + free(ann_obj_name); + return FAIL; + } + + ret = H5Awrite(h5_aid,sh5str_type,(void *)ann_buf); + + if (ret <0) { + printf("failed to obtain attribute.\n "); + ANend(an_id); + free(lab_anno_list); + free(ann_buf); + free(ann_obj_name); + return FAIL; + } + + ret = H5Sclose(h5_sid); + ret = H5Aclose(h5_aid); + free(ann_obj_name); + free(ann_buf); + } + } + + if(num_des_anno > 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 <snum_grattrs;i++) { + + if (GRattrinfo(sri_id,i,sgratrr_name,&sgr_atype,&count_sgradata)==FAIL){ + printf("unable to obtain attribute information. \n"); + return FAIL; + } + + /*convert datatype for attribute. */ + + if(h4type_to_h5type(sgr_atype,&sh5_amemtype,&sh4_amemsize, + &sh4_asize,&sh5_atype)==FAIL){ + printf("unable to do type transferring.\n"); + return FAIL; + } + + sgr_adata = malloc(sh4_amemsize*count_sgradata); + + if(GRgetattr(sri_id,i,(VOIDP)sgr_adata)==FAIL){ + printf("unable to get GR attributes. \n"); + return FAIL; + } + + /* if attribute doesn't have name, a default name is set. */ + if(sgratrr_name[0] == '\0') { + grrepattr_name = trans_obj_name(DFTAG_RIG,i); + strcpy(sgratrr_name,grrepattr_name); + free(grrepattr_name); + } + + /* if the sds attribute is a file attribute. */ + if(check_gloflag == 1){ + strcpy(grglo,GLOIMAGE); + strcat(sgratrr_name,"_"); + strcat(sgratrr_name,grglo); + } + /* now do attribute-transferring. + 1. deal with string data type + 2. set attribute space. + 3. get attribute name, set property list. */ + + if (sh5_atype == H5T_STRING) { + + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create attribute space for IMAGE. \n"); + return FAIL; + } + + if ((sh5str_type = mkstr(count_sgradata*sh4_asize,H5T_STR_SPACEPAD))<0){ + printf("error in making string for image attribute \n"); + return FAIL; + } + + /* check this line later. */ + if ((sh5str_memtype = mkstr(count_sgradata*sh4_amemsize, + H5T_STR_SPACEPAD))<0){ + printf("error in making memory string. \n"); + return FAIL; + } + + sh5a_id = H5Acreate(sh5_dset,sgratrr_name,sh5str_type,sh5a_sid, + H5P_DEFAULT); + if (sh5a_id <0) { + printf("failed to obtain attribute id for IMAGE. \n"); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)sgr_adata); + + if (sret <0) { + printf("failed to obtain attribute of IMAGE.\n "); + return FAIL; + } + + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + + else { + + if (count_sgradata == 1) { + + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create space id. \n"); + return FAIL; + } + } + else { + + sh5dims[0] = count_sgradata; + sh5a_sid = H5Screate_simple(1,sh5dims,NULL); + + if (sh5a_sid < 0) { + printf("failed to create attribute space. \n"); + return FAIL; + } + } + + sh5a_id = H5Acreate(sh5_dset,sgratrr_name,sh5_atype,sh5a_sid, + H5P_DEFAULT); + + if(sh5a_id <0) { + printf("failed to obtain attribute id. \n"); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)sgr_adata); + + if(sret <0) { + printf("failed to obtain attribute.\n "); + return FAIL; + } + sret = H5Aclose(sh5a_id); + sret = H5Sclose(sh5a_sid); + + } + + free(sgr_adata); + + } + + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: create_pal_objref + * + * Purpose: create object reference for palette + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + h5dset: hdf5 dataset + h5_palgroup: hdf5 palette group + h5pal_name: hdf5 palette name + + Out: + *------------------------------------------------------------------------- + */ + +int create_pal_objref(hid_t h5dset,hid_t h5_palgroup,char *h5pal_name){ + + hobj_ref_t pal_refdat; + hsize_t pal_refDims[1]; + hid_t pal_refSpace; + hid_t pal_refType; + hid_t attribID; + herr_t ret; + + pal_refDims[0] = 1; + pal_refSpace = H5Screate_simple(1,pal_refDims,NULL); + + if(pal_refSpace < 0) { + printf("error in obtaining reference space. \n"); + return FAIL; + } + + pal_refType = H5Tcopy(H5T_STD_REF_OBJ); + if(pal_refType < 0) { + printf("error in obtaining reference type. \n"); + H5Sclose(pal_refSpace); + return FAIL; + } + + ret = H5Rcreate(&pal_refdat,h5_palgroup,h5pal_name, + H5R_OBJECT,-1); + if(ret < 0) { + printf("error in creating reference space. \n"); + H5Sclose(pal_refSpace); + H5Tclose(pal_refType); + return FAIL; + } + + attribID = H5Acreate(h5dset,PALETTE,pal_refType,pal_refSpace, + H5P_DEFAULT); + + if(attribID < 0) { + printf("error in obtaining attribute ID. \n"); + H5Sclose(pal_refSpace); + H5Tclose(pal_refType); + return FAIL; + } + + ret = H5Awrite(attribID,pal_refType,(void *)&pal_refdat); + + + H5Sclose(pal_refSpace); + if(H5Tclose(pal_refType)<0) { + printf("error closing palette reference type.\n"); + H5Aclose(attribID); + } + H5Aclose(attribID); + return SUCCEED; +} diff --git a/tools/h4toh5/h4toh5main.c b/tools/h4toh5/h4toh5main.c new file mode 100644 index 0000000..e9ef567 --- /dev/null +++ b/tools/h4toh5/h4toh5main.c @@ -0,0 +1,1629 @@ +/*------------------------------------------------------------------------- + * + * 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 + +This file describes the main driver of hdf to hdf5 converter. It checks +the inputting parameters, initializes the global tables, sets up the root level +hdf5 structure and also check the special case fof vgroup loops at HDF file. + + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + + +#include "h4toh5main.h" + +int32 estnum_vg; +int32 estnum_vd; +int32 num_sds; +int32 num_images; +int num_objects; +int32 num_glsdsattrs; +int32 num_glgrattrs; +struct table* sds_hashtab; +struct table* gr_hashtab; +struct table* vg_hashtab; +struct table* vd_hashtab; +struct table* pal_hashtab; +struct name_table* name_hashtab; +struct name_table* dim_hashtab; + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: driver routine to handle all objects of hdf4 file. + * + * Return: FAIL if failed, SUCCEED if successful. + + Modfication: + *------------------------------------------------------------------------- + */ + + + +int main(int argc, char ** argv) { + + char *h5_filename=NULL; + char *h4_filename=NULL; + char *h5_extension; + int status = 0; + + argc--; + argv++; + + if (argc == 0) { + fprintf(stderr,"\nError: Invalid Arguments\n"); + PrintOptions_h4toh5(); + return FAIL; + } + + /* take care -h (help) option first */ + { int i; + for (i=0; i < argc; i++) + if ( HDstrcmp(argv[i],"-h") == 0 ) { + PrintOptions_h4toh5(); + return SUCCEED; + } + } + + + switch(argc) { + + case 0: + + PrintOptions_h4toh5(); + break; + + case 1: /* h4toh5 file1 */ + h4_filename = argv[0]; +#ifndef WIN32 + if (test_file(h4_filename,O_EXCL,292) != 0 ) { + /* 292 Decimal - 0444 Octal, a+r */ + printf("the current hdf4 file name is not set properly.\n"); + status = -1; + break; + } + if (test_dir(h4_filename) != 0 ) { + fprintf(stderr,"%s: Is a directory\n",h4_filename); + status = -1; + break; + } +#endif + /*0. check whether this file is an hdf file. */ + + if(!Hishdf(h4_filename)){ + printf("error: not an hdf file. \n"); + printf("the file will not be converted. \n"); + status = -1; + break; + } + h5_extension = HDstrdup("h5"); + h5_filename = BuildFilename(h4_filename,h5_extension); + if (h5_filename == NULL) { + printf("error in creating hdf5 file name.\n"); + status = -1; + break; + } +#ifndef WIN32 + if (test_file(h5_filename,O_CREAT|O_EXCL,436) != 0) { + /* 436 Decimal - 0664 Octal, ug+rw,o+r */ + printf("permission of hdf5 file is not set properly.\n"); + status = -1; + break; + } +#endif + status = h4toh5(h4_filename, h5_filename); + + if ( status == FAIL ) { + printf("error in converting %s into %s\n",h4_filename,h5_filename); + break; + } + if (h5_filename != NULL) { + HDfree(h5_filename); + } + + break; + + case 2: /* h4toh5 file_in file_out */ + + h4_filename = argv[0]; + h5_filename = argv[1]; + +#ifndef WIN32 + if (test_file(h4_filename,O_EXCL,292) != 0 ) { + /* 292 Decimal - 0444 Octal, a+r */ + printf("permission of hdf4 file is not set properly.\n"); + status = -1; + break; + } + + if (test_dir(h4_filename) != 0 ) { + fprintf(stderr,"%s: Is a directory\n",h4_filename); + status = -1; + break; + } + +#endif + /*0. check whether this file is a hdf file. */ + + if(!Hishdf(h4_filename)){ + printf("error: not an hdf file. \n"); + printf("the file will not be converted. \n"); + status = -1; + break; + } + +#ifndef WIN32 + if (test_file(h5_filename,O_CREAT|O_RDWR,436) != 0) { /* 436 Decimal - 0664 Octal, ug+rw,o+r */ + printf("permission of hdf5 file is not set properly.\n"); + status = -1; + break; + } + + if (test_dir(h4_filename) != 0 ) { + fprintf(stderr,"%s: Is a directory\n",h4_filename); + status = -1; + break; + } + +#endif + status = h4toh5(h4_filename, h5_filename); + if ( status == FAIL ) { + printf("error in converting %sinto %s\n",h4_filename,h5_filename); + break; + } + break; + + default: + break; + } + + return status; + +} + +/*------------------------------------------------------------------------- + * Function: h4toh5 + * + * Purpose: This routine checks out arguments sent, makes sure that hdf4 + file is valid, makes sure filename for hdf5 file is correct, + and then call h4toh5(). + + *------------------------------------------------------------------------- + */ +int h4toh5(char*filename4, char*filename5) { + + /* define variables for hdf4. */ + int32 istat ; /* hdf4 library routine return value. */ + int32 file_id;/* file identfier of hdf file.*/ + int32 sd_id;/* sd interface identifer*/ + int32 gr_id;/* gr interface identifer*/ + int check_glo; + + /* define variables for hdf5. */ + hid_t file5_id;/* hdf5 file identifier. */ + hid_t h5_root;/* new hdf5 root group identifier.*/ + + hid_t h5_dimg;/* hdf5 dimensional scale group identifier. */ + hid_t h5_palg;/* hdf5 palette group identifier. */ + + /*1. open the current hdf4 file. */ + + file_id = Hopen(filename4, DFACC_READ, 0); + if(file_id == FAIL) { + printf("error: no such hdf4 files. \n"); + return FAIL; + } + + /* open sd interface.*/ + sd_id = SDstart(filename4,DFACC_READ); + if(sd_id == FAIL) { + printf("error: cannot start SD interface. \n"); + Hclose(file_id); + return FAIL; + } + + /* open gr interface.*/ + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("error in obtaining gr id. \n"); + SDend(sd_id); + Hclose(file_id); + return FAIL; + } + + /* open V interface. */ + istat = Vstart(file_id); + if(istat == FAIL) { + printf("error in starting V interface. \n"); + SDend(sd_id); + GRend(gr_id); + Hclose(file_id); + return FAIL; + } + + /* 2. obtain number of hdf4 objects(sds,image,vdata,vgroup,palette) + in this hdf4 file. */ + + if(get_numof_hdf4obj(filename4,file_id) == FAIL) { + printf("error in obtaining number of hdf4 objects.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + return FAIL; + } + + /* set up global hash tables for hdf4 objects. */ + if(set_hashtables() == FAIL){ + printf("error in setting hashtables. \n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + return FAIL; + } + + /* create hdf5 file. */ + file5_id = H5Fcreate(filename5,H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT); + + if (file5_id < 0) { + fprintf(stderr, "unable to create hdf5 file \n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + free_allhashmemory(); + return FAIL; + } + + /* Initialize hdf5 group interface. */ + h5_root = H5Gopen(file5_id,"/"); + + if(h5_root < 0) { + printf("error in opening hdf5 root group. \n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /**** build up helper groups(dimensional scale and palette) ****/ + if(set_helpgroups(h5_root,&h5_dimg,&h5_palg)==FAIL) { + printf("error setting up dimensional scale and palette groups.\n"); + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /* convert global sds attributes into global attributes under root group.*/ + check_glo = 1; + + if(sds_transattrs(sd_id, h5_root,num_glsdsattrs,check_glo)==FAIL) { + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + + /* convert global image attributes into global attributes under root group.*/ + check_glo = 1; + + if(gr_tranattrs(gr_id, h5_root,num_glgrattrs,check_glo)==FAIL) { + SDend(sd_id); + GRend(gr_id); + Vend(file_id); + Hclose(file_id); + H5Fclose(file5_id); + free_allhashmemory(); + return FAIL; + } + + /* convert all objects in lone vgroups into corresponding hdf5 objects. */ + if(h4toh5lonevgs(file_id,sd_id,h5_root,h5_dimg,h5_palg)== FAIL) { + printf("error in translating lone vgroup 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 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 + + 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;i<num_sds;i++){ + + sds_id = SDselect(sd_id,i); + + if (sds_id == FAIL) { + printf("error in obtaining sd id.\n"); + return FAIL; + } + + /* if this sds is dimensional scale, the converting should be ignored. dimensional scale will be converted separately. */ + if(SDiscoordvar(sds_id)) continue; + + /* obtain sds information. */ + if(SDgetinfo(sds_id,sds_name,&sds_rank,sds_dimsizes, + &sds_dtype,&num_sdsattrs)== FAIL) { + printf("error in obtaining SD info at "); + printf("the unvisited sds routine.\n"); + SDendaccess(sds_id); + return FAIL; + } + + /* obtain object reference number of the current sds dataset.*/ + obj_ref = SDidtoref(sds_id); + if(obj_ref == FAIL) { + printf("error in obtaining sds object reference at "); + printf("the unvisited sds routine.\n"); + SDendaccess(sds_id); + return FAIL; + } + + /* convert object reference number into string format. */ + if(conv_int_str(obj_ref,refstr) == FAIL) { + printf("error in converting integer into string.\n"); + SDendaccess(sds_id); + return FAIL; + } + + /* check whether the current sds is visited or not. */ + check_sds = lookup(obj_ref,2*num_sds,sds_hashtab); + + /* if not visited, we will do the convertion. */ + + if(check_sds == 0) { + /* since different hdf sds may hold the same name and it is also + legal that sds may not have a name; but for hdf5 dataset, + it must hold a name, so we will use get_obj_aboname to assure + that each new hdf5 dataset converted from + sds objects will have a disabiguous name. */ + + /* checking whether vgroup name contains ORI_SLASH, changing into CHA_SLASH.*/ + cor_sdsname = correct_name(sds_name); + if(cor_sdsname == NULL) { + printf("error in generating corrected sds name. \n"); + SDendaccess(sds_id); + return FAIL; + } + + h5csds_name = get_obj_aboname(cor_sdsname,refstr,NULL,HDF4_SDS); + if(h5csds_name == NULL) { + printf("error in obtaining sds name.\n"); + SDendaccess(sds_id); + free(cor_sdsname); + return FAIL; + } + free(cor_sdsname); + /* put this name into hashtable. */ + if(set_name(obj_ref,2*num_sds,sds_hashtab,h5csds_name)==FAIL) { + printf("error in setting object name.\n"); + SDendaccess(sds_id); + free(h5csds_name); + return FAIL; + } + + /* do the convertion from sds into hdf5 dataset.*/ + if(Sds_h4_to_h5(file_id,sds_id,h5root,h5_dimg)== FAIL){ + printf("error in translating sds into hdf5 dataset.\n"); + SDendaccess(sds_id); + free(h5csds_name); + return FAIL; + } + free(h5csds_name); + + } + SDendaccess(sds_id); + + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: h4toh5unvisitedimages + * + * Purpose: convert unvisited images into hdf5 dataset and put it + under hdf5 root group + This routine will cover old hdf file. + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf file id + h5_root: hdf5 root id + h5_palg: hdf5 palette group id + + Out: + Modification: + *------------------------------------------------------------------------- + */ + +int h4toh5unvisitedimages(int32 file_id,hid_t h5_root,hid_t h5_palg) { + + int i; + int32 istat; + int32 gr_id; + int32 ri_id;/*raster image identifer.*/ + char image_name[MAX_GR_NAME];/* image name.*/ + char* cor_imagename; + int check_image;/* flag to check whether this image is visited. 1 for visited and 0 for non-visited.*/ + int32 obj_ref; /* obj reference number assigned to sds and images.*/ + char refstr[MAXREF_LENGTH];/*object reference number in character string format.*/ + char *h5cimage_name;/* absolute path name of hdf5 dataset transferred from old image.*/ + + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("error in obtaining gr id. \n"); + return FAIL; + } + + /* check all images. */ + for (i=0;i<num_images;i++) { + + ri_id = GRselect(gr_id,i); + if(ri_id ==FAIL) { + printf("error in selecting gr interface.\n"); + return FAIL; + } + + /* obtain information of GR */ + istat = GRgetiminfo(ri_id, image_name, NULL, NULL, NULL, NULL, NULL); + + if(istat == FAIL) { + printf("error in getting GR images.\n"); + GRendaccess(ri_id); + return FAIL; + } + + /* obtain object reference number and convert it into string format. */ + obj_ref = GRidtoref(ri_id); + if(obj_ref == 0) { + printf("error in obtaining image reference number"); + printf(" at h4toh5unvisitedimages routine.\n"); + GRendaccess(ri_id); + return FAIL; + } + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("error in converting object reference number"); + printf(" into string at h4toh5unvisitedimages routine.\n"); + GRendaccess(ri_id); + return FAIL; + } + + /* check whether the current image is visited or not. */ + check_image = lookup(obj_ref,2*num_images,gr_hashtab); + + if(check_image == 0) { + + /* since different hdf image may hold the same name and it is + also legal that an image may not have a name; but for hdf5 + dataset, it must hold a name, so we will use get_obj_aboname + to guarrtte that each new hdf5 dataset converted from + image objects will have a disabiguous name. */ + + /* checking whether vgroup name contains ORI_SLASH, + changing into CHA_SLASH.*/ + + cor_imagename = correct_name(image_name); + if(cor_imagename == NULL) { + printf("error in generating corrected image name. \n"); + GRendaccess(ri_id); + return FAIL; + } + h5cimage_name = get_obj_aboname(cor_imagename,refstr,NULL, + HDF4_IMAGE); + if(h5cimage_name == NULL) { + printf("error in getting image name.\n"); + GRendaccess(ri_id); + free(cor_imagename); + return FAIL; + } + free(cor_imagename); + + if(set_name(obj_ref,2*num_images,gr_hashtab,h5cimage_name)==FAIL) { + printf("error setting image name.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + return FAIL; + } + + /* do the convertion from the image into hdf5 dataset.*/ + if(Image_h4_to_h5(file_id,ri_id,h5_root,h5_palg)== FAIL) { + printf("error in transferring image name into hdf5 dataset.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + return FAIL; + } + free(h5cimage_name); + } + GRendaccess(ri_id); + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: free_allhashmemory() + * + * Purpose: free memory allocated for all hashtables + * + * Return: + * + * In : + + + Out: + Modification: + *------------------------------------------------------------------------- + */ + +void free_allhashmemory(){ + + if(estnum_vg != 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); + +} + + + +/********The following routines are adapted from h5toh4 converter. *******/ +/***************************************************************************** + + Routine: test_file + + Description: Test a file for read/write - ability. + + Input: filename - Unix filename + + Output: function return, global variable - errno + +*****************************************************************************/ + +int test_file(char *filename,int oflag,mode_t mode) +{ + int fid; + + errno = 0; + + fid = open(filename, oflag, mode); + if (fid < 0) { + perror(filename); + } + close(fid); + + return errno; + +} + + +/***************************************************************************** + + Routine: test_dir + + Description: Test pathway to determine if it is a directory + + Input: path - pathname given + + Output: function return TRUE/FALSE + +*****************************************************************************/ + +int test_dir(char *path) +{ + + struct stat buf; + struct stat *buf_ptr; + int idir; + + buf_ptr = &buf; + + idir = stat(path, buf_ptr); + if (idir < 0) { + if (errno == 2) { + return 0; + } else { + perror(path); + } + } + + return S_ISDIR(buf_ptr->st_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 <fcntl.h> +#include <errno.h> +#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<sds_rank;i++){ + sds_stride[i] = 1; + sds_start[i] = 0; + sds_edge[i] = sds_dimsizes[i]; + count_sdsdata = count_sdsdata*sds_dimsizes[i]; + + } + + for (i=0;i<sds_rank;i++) { + h5dims[i] = sds_edge[i]-sds_start[i]; + max_h5dims[i] = h5dims[i]; + } + if(SDisrecord(sds_id)) max_h5dims[0] = H5S_UNLIMITED; + + /* convert hdf4 data type to hdf5 data type. */ + if (h4type_to_h5type(sds_dtype,&h5_memtype,&h4memsize,&h4size, + &h5ty_id) == FAIL) { + printf("failed to translate datatype. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + return FAIL; + } + + /* check whether the datatype is string, if we find string format, + we will change them back into integer format.*/ + + if (h5ty_id == H5T_STRING) { + /* rechange string datatype into numerical datatype.*/ + if(h5string_to_int(sds_dtype,&h5_memtype,h4memsize, + &h5ty_id)== FAIL) { + printf("error in translating H5T_STRING to int.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + return FAIL; + } + } + + sds_data = malloc(h4memsize*count_sdsdata); + if(sds_data == NULL) { + printf("error in allocating memory. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + return FAIL; + } + + istat = SDreaddata(sds_id, sds_start, sds_stride, sds_edge, + (VOIDP)sds_data); + if (istat == FAIL) { + printf("unable to read data from h5dset. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + return FAIL; + } + + /* obtaining reference number and name of h5 dataset + corresponding to sds. */ + + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("error in obtaining sds reference number. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + return FAIL; + } + + h5csds_name = get_name(sds_ref,2*num_sds,sds_hashtab,&check_sdsname); + if (h5csds_name == NULL && check_sdsname == 0 ) { + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + printf("error,cannot find sds name \n"); + return FAIL; + } + + if (h5csds_name == NULL && check_sdsname == -1) { + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + printf("error,sds name is not defined.\n"); + return FAIL; + } + + if (h5csds_name == NULL && check_sdsname == -2) { + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + printf("error,not enough memory for allocating sds name.\n"); + return FAIL; + } + + h5d_sid = H5Screate_simple(sds_rank,h5dims,max_h5dims); + + if (h5d_sid < 0) { + printf("failed to create hdf5 data space converted from SDS. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + return FAIL; + } + + /* create property list. */ + + create_plist = H5Pcreate(H5P_DATASET_CREATE); + chunk_dims = malloc(sizeof(hsize_t)*sds_rank); + + /* if the sds is not chunked, but with unlimited dimension, we have to + provide a chunk size for the corresponding hdf5 dataset. we will choose + 1/2 dimension size right now. */ + + if(c_flags == HDF_NONE && SDisrecord(sds_id)) + { + for(i=0;i<sds_rank;i++){ + chunk_dims[i] = (hsize_t)(h5dims[i]/2); + } + if(H5Pset_chunk(create_plist, sds_rank, chunk_dims)<0) { + printf("failed to set up chunking information for "); + printf("property list.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Pclose(create_plist); + return FAIL; + } + + } + if(c_flags == HDF_CHUNK || c_flags == (HDF_CHUNK | HDF_COMP) + || c_flags == (HDF_CHUNK | HDF_NBIT) ){ + + for(i=0;i<sds_rank;i++) + chunk_dims[i] = (hsize_t)c_def_out.chunk_lengths[i]; + + if(H5Pset_chunk(create_plist, sds_rank, chunk_dims)<0) { + printf("failed to set up chunking information for "); + printf("property list.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Pclose(create_plist); + return FAIL; + } + } + + + h5dset = H5Dcreate(h5_group,h5csds_name,h5ty_id,h5d_sid,create_plist); + + if (h5dset < 0) { + printf("failed to create hdf5 dataset converted from SDS. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Pclose(create_plist); + return FAIL; + } + + if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,H5P_DEFAULT, + (void *)sds_data)<0) { + printf("failed to write data into hdf5 dataset"); + printf(" converted from SDS.\n"); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + return FAIL; + } + + + /* convert sds annotation into attribute of sds dataset. + Since there is no routines to find the exact tag of sds object, + we will check three possible object tags of sds objects, that is: + DFTAG_SD,DFTAG_SDG,DFTAG_NDG. If the object tag of sds 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 sds objects are only one of the above three tags.*/ + + if(Annoobj_h4_to_h5(file_id,sds_ref,DFTAG_SD,h5dset)== FAIL){ + printf("failed to convert sds annotation into hdf5 attribute.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + return FAIL; + } + + if(Annoobj_h4_to_h5(file_id,sds_ref,DFTAG_SDG,h5dset)== FAIL){ + printf("failed to convert sds annotation into hdf5 attribute.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + return FAIL; + } + + if(Annoobj_h4_to_h5(file_id,sds_ref,DFTAG_NDG,h5dset)== FAIL){ + printf("failed to convert sds annotation into hdf5 attribute.\n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + return FAIL; + } + + /* convert sds dimensional scale dataset into hdf5 dataset. */ + if(sdsdim_to_h5dataset(sds_id,sds_rank,h5dset,h5_dimgroup,sds_dimsizes[0]) == FAIL) { + printf("failed to convert dimensional scale to hdf5 dataset. \n"); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + return FAIL; + } + check_gloattr = 0; + if (sds_transattrs(sds_id,h5dset,num_sdsattrs,check_gloattr)==FAIL) { + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + printf(" Error in obtaining sds attributes. \n"); + return FAIL; + } + + /********************************************/ + /* handle extra attributes of sds : sds label, object type + and reference num */ + + strcpy(sdslabel,SDSLABEL); + + if(h4_transpredattrs(h5dset,HDF4_OBJECT_TYPE,sdslabel)==FAIL) { + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + printf("unable to transfer sds label to HDF4 OBJECT TYPE.\n"); + return FAIL; + } + + if(sdsname[0] != '\0') { + if(h4_transpredattrs(h5dset,HDF4_OBJECT_NAME,sdsname)==FAIL){ + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + printf("unable to transfer sds name to HDF5 dataset attribute.\n"); + return FAIL; + } + } + + if(h4_transnumattr(h5dset,HDF4_REF_NUM,sds_ref)==FAIL){ + free(sds_start); + free(sds_edge); + free(sds_stride); + free(sds_data); + free(chunk_dims); + H5Sclose(h5d_sid); + H5Dclose(h5dset); + H5Pclose(create_plist); + printf("unable to transfer sds ref. to HDF5 dataset attribute.\n"); + return FAIL; + } + + istat = SDendaccess(sds_id); + ret = H5Pclose(create_plist); + ret = H5Sclose(h5d_sid); + ret = H5Dclose(h5dset); + free(sds_data); + free(sds_start); + free(sds_edge); + free(sds_stride); + free(chunk_dims); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: sds_transattrs + * + * Purpose: translate attribute of HDF4 SDS object into + hdf5 dataset attribute + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + ssds_id: SDS identifier + sh5_dset: hdf5 dataset + snum_sdsattrs: number of sds attribute + check_gloflag: a flag that check whether the attribute is + a file attribute or a sds id or a dimensional scale id. + + *------------------------------------------------------------------------- + */ + +int sds_transattrs(int32 ssds_id, hid_t sh5_dset,int snum_sdsattrs, + int check_gloflag) { + + char ssdsatrr_name[2*MAX_NC_NAME]; + char sdsglo[MAX_NC_NAME]; + char* sdsrepattr_name; + int32 count_ssdsadata; + int32 ssds_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* ssds_adata; + herr_t sret; + int i; + + for (i = 0;i < snum_sdsattrs; i++) { + + if (SDattrinfo(ssds_id,i,ssdsatrr_name,&ssds_atype, + &count_ssdsadata)==FAIL){ + printf("unable to obtain SDS attribute information. \n"); + return FAIL; + } + + /* make a table for the attribute type, to do the corresponding type. */ + + if(h4type_to_h5type(ssds_atype,&sh5_amemtype,&sh4_amemsize, + &sh4_asize,&sh5_atype)== FAIL) { + printf("fail to translate sds attribute data type from H4 to H5. \n"); + return FAIL; + } + + ssds_adata = malloc(sh4_amemsize * count_ssdsadata); + if(ssds_adata == NULL) { + printf("error, cannot allocate memory for sds attribute data. \n"); + return FAIL; + } + + if(SDreadattr(ssds_id,i,(VOIDP)ssds_adata)== FAIL) { + printf("error in reading attributes of sds object. \n"); + free(ssds_adata); + return FAIL; + } + + /* if attribute doesn't have name, a default name is set. */ + if(ssdsatrr_name[0] == '\0') { + sdsrepattr_name = trans_obj_name(DFTAG_NDG,i); + strcpy(ssdsatrr_name,sdsrepattr_name); + free(sdsrepattr_name); + } + + /* if the sds attribute is a file attribute. */ + if(check_gloflag == 1){ + strcpy(sdsglo,GLOSDS); + strcat(ssdsatrr_name,"_"); + strcat(ssdsatrr_name,sdsglo); + } + + /* now do attribute-transferring. + 1. deal with string data type + 2. set attribute space. + 3. get attribute name, set property list. */ + + if (sh5_atype == H5T_STRING) { + + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create attribute space for"); + printf(" HDF4_OBJECT_TYPE SDS. \n"); + free(ssds_adata); + return FAIL; + } + + if ((sh5str_type = mkstr(count_ssdsadata, + H5T_STR_SPACEPAD))<0) { + printf("error in making string. \n"); + H5Sclose(sh5a_sid); + free(ssds_adata); + return FAIL; + } + + /* check this line later. */ + if ((sh5str_memtype = mkstr(count_ssdsadata*sh4_amemsize, + H5T_STR_SPACEPAD))<0) { + printf("error in making memory string. \n"); + H5Sclose(sh5a_sid); + free(ssds_adata); + return FAIL; + } + + sh5a_id = H5Acreate(sh5_dset,ssdsatrr_name,sh5str_type, + sh5a_sid,H5P_DEFAULT); + + if (sh5a_id <0) { + printf("failed to obtain attribute id for"); + printf(" HDF4_OBJECT_TYPE SDS. \n"); + H5Sclose(sh5a_sid); + free(ssds_adata); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)ssds_adata); + + if (sret <0) { + printf("failed to write attribute data for"); + printf(" HDF4_OBJECT_TYPE SDS. \n"); + H5Sclose(sh5a_sid); + H5Aclose(sh5a_id); + free(ssds_adata); + return FAIL; + } + + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + + else { + + if(count_ssdsadata == 1) { + + sh5a_sid = H5Screate(H5S_SCALAR); + if (sh5a_sid < 0) { + printf("failed to create space id. \n"); + free(ssds_adata); + return FAIL; + } + } + else { + sh5dims[0] = count_ssdsadata; + sh5a_sid = H5Screate_simple(1,sh5dims,NULL); + + if (sh5a_sid < 0) { + printf("failed to create attribute space. \n"); + free(ssds_adata); + return FAIL; + } + } + sh5a_id = H5Acreate(sh5_dset,ssdsatrr_name,sh5_atype, + sh5a_sid,H5P_DEFAULT); + + if(sh5a_id <0) { + printf("failed to obtain attribute id. \n"); + H5Sclose(sh5a_sid); + free(ssds_adata); + return FAIL; + } + + sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)ssds_adata); + + if(sret <0) { + printf("failed to write attribute data.\n "); + H5Sclose(sh5a_sid); + H5Aclose(sh5a_id); + free(ssds_adata); + return FAIL; + } + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + free(ssds_adata); + } + return SUCCEED; +} +/****************sdsdim_to_h5dataset******************* + + * Purpose: translate dimensional scale dataset into + hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + sds_id: SDS identifier + sds_rank: number of sds dimensions + Out: + Modification: + + *------------------------------------------------------------------------- + */ + +int sdsdim_to_h5dataset(int32 sds_id,int32 sds_rank,hid_t sh5dset, + hid_t sh5_dimgroup,int32 firstdimsize) { + + int32 sdsdim_id; + int32 sdsdim_type = 0; + int32 sds_dimscasize[1]; + int32 istat; + int i; + int count_h5objref;/* this counter updates the number of h5 object reference. */ + int count_h5attrname;/*this counter updates the number of h5 dimensional name attribute.*/ + + int check_gloattr; + int32 num_sdsdimattrs; + int check_sdsdim; + void* dim_scadata; + + char sdsdim_name[MAX_NC_NAME+1]; + char* cor_sdsdimname; + size_t h4dim_memsize; + size_t h4dim_size; + + HDF_CHUNK_DEF c_def_out; + int32 c_flags; + + /* define varibles for hdf5. */ + + hid_t h5dim_dset; + hid_t h5dim_sid; + + hid_t h5dim_tid; + hid_t h5dim_memtype; + + hid_t h5dim_nameaid; + hid_t h5dim_namesid; + + hid_t h5str_dimntype; + + hid_t attr_refSpace; + hid_t attr_refType; + hid_t attribID; + hid_t create_plist; + + hsize_t h5dimscas[1]; + hsize_t max_h5dimscas[1]; + hsize_t h5dim_dims[1]; + hsize_t attr_refDims[1]; + hsize_t h5dim_chunkdim[1]; + hobj_ref_t dim_refdat; + + hobj_ref_t* alldim_refdat; + + char* h5sdsdim_name; + char h5sdsdim_allname[MAX_VAR_DIMS * MAX_DIM_NAME]; + char h5newsdsdim_name[MAX_DIM_NAME]; + char h5dimpath_name[MAX_DIM_NAME]; + herr_t ret; + + + /*zero out memory for h5sdsdim_allname and h5dimpath_name */ + h4toh5_ZeroMemory(h5sdsdim_allname,(MAX_VAR_DIMS*MAX_DIM_NAME)*sizeof(char)); + h4toh5_ZeroMemory(h5dimpath_name,MAX_DIM_NAME*sizeof(char)); + + /*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; + } + + /* initialize the dimensional number of sds dimensions, h5dim_dims + is used for grabbing hdf5 dimensional name list and object reference + list. */ + h5dim_dims[0] = (hsize_t)sds_rank; + count_h5objref = 0; + count_h5attrname = 0; + + for (i = 0; i<sds_rank;i++) { + + sdsdim_id = SDgetdimid(sds_id,i); + + if(sdsdim_id == FAIL) { + printf("error in obtaining sds dimension id. \n"); + return FAIL; + } + + istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize, + &sdsdim_type,&num_sdsdimattrs); + + if (istat == FAIL) { + printf("sds get dim. information failed. \n"); + SDendaccess(sdsdim_id); + return FAIL; + } + + /* for unlimited sds dimension, grab the current dimensional size. */ + if(sds_dimscasize[0] == 0) sds_dimscasize[0] = firstdimsize; + + /* check whether this dimensional scale dataset is looked up. */ + check_sdsdim = lookup_name(sdsdim_name,DIM_HASHSIZE,dim_hashtab); + + strcpy(h5dimpath_name,HDF4_DIMG); + + /* checking whether sds dimension scale name contains ORI_SLASH, changing into CHA_SLASH.*/ + + cor_sdsdimname = correct_name(sdsdim_name); + if(cor_sdsdimname == NULL) { + printf("error in generating corrected sds dimensional scale name.\n"); + SDendaccess(sdsdim_id); + return FAIL; + } + + /* generating hdf5 dimensional scale name. */ + h5sdsdim_name = get_obj_aboname(cor_sdsdimname,NULL,h5dimpath_name,NULL); + if (h5sdsdim_name == NULL) { + printf("error in getting hdf5 sds dimension name.\n"); + SDendaccess(sdsdim_id); + free(cor_sdsdimname); + return FAIL; + } + free(cor_sdsdimname); + + strcpy(&h5sdsdim_allname[count_h5attrname*MAX_DIM_NAME],h5sdsdim_name); + + /* here we should add some comments for fakedim0--name. It seems that + hdf4(netcdf) will use unique fake dimension name, fakedim + unique + number, so check_sdsdim will never be 1 if the dimension name is fake + name. Under this case, count_h5objref and count_h5attrname + will not increase if this dimension doesnot + have dimensional scale data. That assures the object reference of sds is + correct. */ + + /*if this dimension is not touched, get name of the dimensional scale data. */ + if (check_sdsdim == 1){/* the dimension is touched, skip this one.*/ + free(h5sdsdim_name); + SDendaccess(sdsdim_id); + count_h5objref = count_h5objref + 1; + count_h5attrname = count_h5attrname + 1; + continue; + } + + if (check_sdsdim != 0) { + printf("error in checking sds dimensions.\n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + return FAIL; + } + + /* if this sds dimension has no dimensional scale data. skip it.*/ + if(sdsdim_type == 0) + continue; + + + /* get h5 dimensional scale data type. */ + if(h4type_to_h5type(sdsdim_type,&h5dim_memtype,&h4dim_memsize, + &h4dim_size,&h5dim_tid)== FAIL) { + printf("error in transferring sds dimension data type.\n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + return FAIL; + } + + /* dimensional scale dataset cannot be H5T_STRING data type. + So transferring back to int8 */ + + if (h5dim_tid == H5T_STRING) { + if(h5string_to_int(sdsdim_type,&h5dim_memtype,h4dim_memsize, + &h5dim_tid)==FAIL){ + printf("error in translating from string to int. \n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + return FAIL; + } + } + + /* get the dimensional scale data. */ + dim_scadata = malloc(h4dim_memsize*sds_dimscasize[0]); + istat = SDgetdimscale(sdsdim_id,(VOIDP)dim_scadata); + + if (istat == FAIL) { + printf("sds get dim. scale failed. \n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + free(dim_scadata); + return FAIL; + } + + /* set dimensional scale size properly. */ + h5dimscas[0] = sds_dimscasize[0]; + + /* only set for the first dimension if SDS is unlimited dimension. */ + if(SDisrecord(sds_id) && i == 0) + max_h5dimscas[0] = H5S_UNLIMITED; + else + max_h5dimscas[0] = h5dimscas[0]; + + h5dim_sid = H5Screate_simple(1,h5dimscas,max_h5dimscas); + + if(h5dim_sid <0) { + printf("error in creating space. \n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + free(dim_scadata); + return FAIL; + } + + /* create property list, for chunked sds or unlimited dimension cases */ + + create_plist = H5Pcreate(H5P_DATASET_CREATE); + + if(create_plist == -1) { + printf("failed to create property list. \n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + free(dim_scadata); + H5Sclose(h5dim_sid); + } + + + if(c_flags == HDF_NONE && SDisrecord(sds_id) && i == 0) + { + h5dim_chunkdim[0] = (hsize_t)(h5dimscas[0]/2); + + if(H5Pset_chunk(create_plist,1, h5dim_chunkdim)<0) { + printf("failed to set up chunking information for "); + printf("dimensional scale property list.\n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + free(dim_scadata); + H5Sclose(h5dim_sid); + H5Pclose(create_plist); + return FAIL; + } + + } + + if(c_flags == HDF_CHUNK || c_flags == (HDF_CHUNK | HDF_COMP) + || c_flags == (HDF_CHUNK | HDF_NBIT) ){ + + h5dim_chunkdim[0] = (hsize_t)c_def_out.chunk_lengths[0]; + + if(H5Pset_chunk(create_plist,1, h5dim_chunkdim)<0) { + printf("failed to set up chunking information for "); + printf("property list.\n"); + SDendaccess(sdsdim_id); + free(h5sdsdim_name); + free(dim_scadata); + H5Sclose(h5dim_sid); + H5Pclose(create_plist); + return FAIL; + } + } + + /* create h5 dataset under group HDF4_DIMG*/ + h5dim_dset = H5Dcreate(sh5_dimgroup,h5sdsdim_name,h5dim_tid, + h5dim_sid,create_plist); + + if(h5dim_dset <0) { + printf("error in creating dataset. \n"); + free(h5sdsdim_name); + free(dim_scadata); + SDendaccess(sdsdim_id); + H5Sclose(h5dim_sid); + H5Pclose(create_plist); + return FAIL; + } + + if (H5Dwrite(h5dim_dset,h5dim_memtype,h5dim_sid,h5dim_sid, + H5P_DEFAULT,(void *)dim_scadata)<0) { + printf("error writing data\n"); + free(h5sdsdim_name); + free(dim_scadata); + SDendaccess(sdsdim_id); + H5Sclose(h5dim_sid); + H5Pclose(create_plist); + H5Dclose(h5dim_dset); + return FAIL; + } + + check_gloattr = 0; + if(sds_transattrs(sdsdim_id,h5dim_dset,num_sdsdimattrs,check_gloattr) + == FAIL){ + printf("error in transferring attributes. \n"); + free(h5sdsdim_name); + free(dim_scadata); + SDendaccess(sdsdim_id); + H5Sclose(h5dim_sid); + H5Dclose(h5dim_dset); + H5Pclose(create_plist); + return FAIL; + } + SDendaccess(sdsdim_id); + free(dim_scadata); + free(h5sdsdim_name); + ret = H5Sclose(h5dim_sid); + ret = H5Dclose(h5dim_dset); + ret = H5Pclose(create_plist); + count_h5objref = count_h5objref + 1; + count_h5attrname =count_h5attrname + 1; + } + + /*1. create object reference number to dimensional scale dataset. + 2. store absolute name of dimensional name into + dimensional list. */ + + if ( count_h5objref != 0) { + + h5dim_dims[0] = count_h5objref; + attr_refDims[0] = count_h5objref; + attr_refSpace = H5Screate_simple(1,attr_refDims,NULL); + attr_refType = H5Tcopy(H5T_STD_REF_OBJ); + alldim_refdat = calloc((size_t)count_h5objref,sizeof(hobj_ref_t)); + + if(alldim_refdat == NULL) { + printf("error in allocating memory. \n"); + H5Sclose(attr_refSpace); + H5Tclose(attr_refType); + return FAIL; + } + + for(i=0;i<count_h5objref;i++){ + h4toh5_ZeroMemory(h5newsdsdim_name,MAX_DIM_NAME); + strcpy(h5newsdsdim_name,&h5sdsdim_allname[i*MAX_DIM_NAME]); + + ret = H5Rcreate(&dim_refdat,sh5_dimgroup,h5newsdsdim_name, + H5R_OBJECT,-1); + if(ret <0) { + free(alldim_refdat); + H5Sclose(attr_refSpace); + H5Tclose(attr_refType); + printf("error in generating H5 reference. \n"); + return FAIL; + } + alldim_refdat[i] = dim_refdat; + + } + + attribID = H5Acreate(sh5dset,DIMSCALE,attr_refType,attr_refSpace, + H5P_DEFAULT); + if(attribID < 0) { + free(alldim_refdat); + H5Sclose(attr_refSpace); + H5Tclose(attr_refType); + H5Aclose(attribID); + printf("error in generating H5 attribute ID. \n"); + return FAIL; + } + + ret = H5Awrite(attribID,attr_refType,(void *)alldim_refdat); + + H5Sclose(attr_refSpace); + H5Tclose(attr_refType); + H5Aclose(attribID); + free(alldim_refdat); + } + + if(count_h5attrname!= 0) { + + h5dim_namesid = H5Screate_simple(1,h5dim_dims,NULL); + + if(h5dim_namesid <0) { + printf("error in creating sds dimensionlist space.\n"); + return FAIL; + } + + h5str_dimntype = mkstr(MAX_DIM_NAME,H5T_STR_SPACEPAD); + if(h5str_dimntype < 0) { + H5Sclose(h5dim_namesid); + printf("error in generating H5T_STRING type.\n"); + return FAIL; + } + + h5dim_nameaid = H5Acreate(sh5dset,HDF4_DIMENSION_LIST,h5str_dimntype, + h5dim_namesid,H5P_DEFAULT); + + if(h5dim_nameaid <0) { + H5Sclose(h5dim_namesid); + printf("error in creating sds dimensionlist id.\n"); + return FAIL; + } + + ret = H5Awrite(h5dim_nameaid,h5str_dimntype,h5sdsdim_allname); + + if(ret < 0) { + H5Sclose(h5dim_namesid); + H5Aclose(h5dim_nameaid); + printf("error in writing sds dimensionlist. \n"); + return FAIL; + } + + ret = H5Sclose(h5dim_namesid); + ret = H5Aclose(h5dim_nameaid); + + } + return SUCCEED; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/h4toh5/h4toh5test.c b/tools/h4toh5/h4toh5test.c new file mode 100644 index 0000000..1f21b63 --- /dev/null +++ b/tools/h4toh5/h4toh5test.c @@ -0,0 +1,3944 @@ +/*** this code is to generate various hdf files to test h4toh5 converter and h4toh5 lib API. The code itself is NOT optimizied but try to consider various cases that examine how converter works. */ + +#include "hdf.h" +#include "mfhdf.h" +#include <stdio.h> + + +#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;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++){ + typchar_array[i][j][k]=(char) (i+j+k); + } + + /* data type is int8 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typint8_array[i][j][k]= (int8)(INT8_UPLIMIT-i*j*k*2/CUB_SIZE*INT8_UPLIMIT +1); + + /* data type is int16 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typint16_array[i][j][k]= (int16)(INT16_UPLIMIT-i*j*k*2/CUB_SIZE*INT16_UPLIMIT +1); + + /* data type is uint16 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typuint16_array[i][j][k]= (uint16)(UINT16_UPLIMIT-i*j*k*2/CUB_SIZE*(UINT16_UPLIMIT/2)+1); + + /* data type is int32 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typint32_array[i][j][k]= INT32_UPLIMIT-i*j*k*2/CUB_SIZE*INT32_UPLIMIT +1; + + /*data type is little-endian int32*/ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typlint32_array[i][j][k]= INT32_UPLIMIT-i*j*k*2/CUB_SIZE*INT32_UPLIMIT +1; + + /* data type is unsigned little-endian int32*/ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typluint32_array[i][j][k]= (uint32)(UINT32_UPLIMIT-i*j*k/CUB_SIZE*UINT32_UPLIMIT+1); + + /* data type is float32 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typfloat32_array[i][j][k]= 1.0+i+j+k; + + /* data type is float64 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typfloat64_array[i][j][k]= 1.0+i+j+k; + + /* data type is lfloat64 */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typlfloat64_array[i][j][k]= 1.0+i+j+k; + + for(i=0;i<TYP_RANK;i++){ + typ_dims[i] = TYP_DIMSIZE; + typ_start[i] = 0; + typ_edges[i] = TYP_DIMSIZE; + typ_stride[i] = 1; + } + + file_id = SDstart(FILESDS1,DFACC_CREATE); + + if(file_id == FAIL) { + printf (" open file failed\n"); + return FAIL; + } + + /* we also test different dimensional scale setting for typical array. */ + sds_id = SDcreate(file_id,"sds_char",DFNT_CHAR8,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typchar_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_int8",DFNT_INT8,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typint8_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_int16",DFNT_INT16,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typint16_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_int32",DFNT_INT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typint32_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_uint16",DFNT_UINT16,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typuint16_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_lint32",DFNT_LINT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typlint32_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_luint32",DFNT_LUINT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typluint32_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_float32",DFNT_FLOAT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typfloat32_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_float64",DFNT_FLOAT64,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typfloat64_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(file_id,"sds_lfloat64",DFNT_LFLOAT64,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typlfloat64_array); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + SDend(file_id); + return 0; +} +/* generating a hdf file with sds dimensional scale dataset in it. + both limited and unlimited dimensions are provided.*/ +int test_sdsdim() { + + int32 file_id,sds_id,dim_id; + int32 i,j,k; + int32 typ_start[TYP_RANK],typ_edges[TYP_RANK],typ_stride[TYP_RANK]; + int32 typ_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 typ_dims[TYP_RANK]; + int32 dim_sca0[TYP_DIMSIZE]; + int32 istat; + + char dim_name0[] = "dim0"; + char dim_name1[] = "dim1"; + char dim_name2[] = "dim2"; + + char unldim_name0[] ="unldim0"; + char unldim_name1[]="unldim1"; + char unldim_name2[]="unldim2"; + + /* typical sds array. */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typ_array[i][j][k] = i+j+k; + + for (i=0;i<TYP_DIMSIZE;i++) + dim_sca0[i] = i; + + + for(i=0;i<TYP_RANK;i++){ + typ_dims[i] = TYP_DIMSIZE; + typ_start[i] = 0; + typ_edges[i] = TYP_DIMSIZE; + typ_stride[i] = 1; + } + + file_id = SDstart(FILESDS2,DFACC_CREATE); + + if(file_id == FAIL){ + printf (" open file failed\n"); + return FAIL; + } + + /* testing for normal dimensional scale dataset. */ + sds_id = SDcreate(file_id,"sds_dimnor",DFNT_INT32,TYP_RANK,typ_dims); + + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + + + istat=SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typ_array); + + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + + for (i =0;i<TYP_RANK;i++){ + dim_id = SDgetdimid(sds_id,i); + + if(dim_id == FAIL) { + printf("failed to generate dimensional id.\n"); + return FAIL; + } + + switch(i) { + + case 0: + istat = SDsetdimname(dim_id,dim_name0); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat =SDsetdimscale(dim_id,typ_dims[0],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + case 1: + istat = SDsetdimname(dim_id,dim_name1); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,typ_dims[1],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + case 2: + istat = SDsetdimname(dim_id,dim_name2); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,typ_dims[2],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + } + + } + SDendaccess(sds_id); + + /* for unlimited dimensional scale data. */ + + typ_dims[0] = SD_UNLIMITED; + + sds_id = SDcreate(file_id,"sds_dimunl",DFNT_INT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + + istat =SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typ_array); + if(istat == FAIL) { + printf("failed to write sds object. \n"); + return FAIL; + } + for (i =0;i<TYP_RANK;i++){ + dim_id = SDgetdimid(sds_id,i); + if(dim_id == FAIL) { + printf("failed to generate dimensional id.\n"); + return FAIL; + } + switch(i) { + + case 0: + istat= SDsetdimname(dim_id,unldim_name0); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + /* SDsetdimscale(dim_id,typ_dims[0],DFNT_INT32,(VOIDP)dim_sca0);*/ + istat= SDsetdimscale(dim_id,TYP_DIMSIZE,DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + case 1: + istat= SDsetdimname(dim_id,unldim_name1); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,typ_dims[1],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + case 2: + istat = SDsetdimname(dim_id,unldim_name2); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,typ_dims[2],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + break; + } + } + SDendaccess(sds_id); + + SDend(file_id); + return 0; +} + +/* a hdf file that includes sds predefined attributes, dimensional + scale attributes and chunking and compress information*/ +int test_sdsattr() { + + int32 file_id,sds_id,dim_id; + int32 i,j,k,comp_flag; + int32 typ_start[TYP_RANK],typ_edges[TYP_RANK],typ_stride[TYP_RANK]; + int32 typ_array[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 typ_dims[TYP_RANK]; + int32 fill_value; + int32 dim_sca0[TYP_DIMSIZE],dim_sca1[TYP_DIMSIZE]; + + HDF_CHUNK_DEF c_def; + int32 comp_type; + comp_info c_info; + int32 istat; + float64 cal; + float64 cal_err; + float64 offset; + float64 offset_err; + + char* attr_value; + char* gloattr_value; + char label[] = "sds.label"; + char unit[] = "sds.unit"; + char format[] = "sds.format"; + char coordsys[] = "sds.coord"; + + char dim_name0[] ="dim0"; + char dim_name1[] ="dim1"; + char dim_label[] ="dim.label"; + char dim_unit[] ="dim.unit"; + char dim_format[] ="dim.format"; + + /**** initial setting. ****/ + cal = 1.0; + cal_err = 0.0; + offset = 0.0; + offset_err = 0.0; + fill_value = 999; + + + /* typical sds array. */ + for (i=0;i<TYP_DIMSIZE;i++) + for (j=0;j<TYP_DIMSIZE;j++) + for (k=0;k<TYP_DIMSIZE;k++) + typ_array[i][j][k]= i+j+k; + + attr_value = malloc(ATT_SIZE*sizeof(char)); + if(attr_value == NULL) { + printf("failed to allocate memory. \n"); + return FAIL; + } + + gloattr_value = malloc(ATT_SIZE*sizeof(char)); + if(gloattr_value == NULL) { + printf("failed to allocate memory. \n"); + return FAIL; + } + + strcpy(gloattr_value,"glo attr"); + strcpy(attr_value,"test attr"); + + for(i=0;i<TYP_RANK;i++){ + typ_dims[i] = TYP_DIMSIZE; + typ_start[i] = 0; + typ_edges[i] = TYP_DIMSIZE; + typ_stride[i] = 1; + } + + for (i=0;i<TYP_DIMSIZE;i++){ + dim_sca0[i] = i; + dim_sca1[i] = 2*i; + } + file_id = SDstart(FILESDS3,DFACC_CREATE); + + if(file_id == FAIL) { + printf (" open file failed\n"); + return FAIL; + } + + istat = SDsetattr(file_id,"sds.gloattr",DFNT_CHAR8,10,(VOIDP)gloattr_value); + if(istat == FAIL) { + printf("failed to set attribute.\n"); + return FAIL; + } + + istat = SDsetfillmode(file_id,SD_NOFILL); + + if (istat == FAIL) { + printf("error setting fill mode\n"); + return FAIL; + } + + sds_id = SDcreate(file_id,"sds_attr",DFNT_INT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + + istat = SDsetfillvalue(sds_id,(VOIDP)(&fill_value)); + if (istat == FAIL){ + printf("error setting fill value\n"); + return FAIL; + } + + istat = SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typ_array); + + if(istat == FAIL) { + printf("failed to write sds data.\n"); + return FAIL; + } + /*** write dataset attribute ***/ + + istat = SDsetattr(sds_id,"sds.attr",DFNT_CHAR8,10,(VOIDP)attr_value); + if(istat == FAIL) { + printf(" sds data attr. setting failed. \n"); + return FAIL; + } + /*** write dataset predefined attribute ***/ + + istat = SDsetdatastrs(sds_id,label,unit,format,coordsys); + if(istat == FAIL) { + printf(" sds data predefined attr. setting failed. \n"); + return FAIL; + } + /*** set calibration information. ***/ + + istat = SDsetcal(sds_id,cal,cal_err,offset,offset_err,DFNT_INT32); + if(istat == FAIL) { + printf(" sds data calibrating attr. setting failed. \n"); + return FAIL; + } + for (i =0; i<TYP_RANK;i++) { + dim_id = SDgetdimid(sds_id,i); + if(dim_id == FAIL) { + printf("sds set dim id failed. \n"); + return FAIL; + } + if (i==0) { + istat = SDsetdimname(dim_id,dim_name0); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat=SDsetdimscale(dim_id,typ_dims[0],DFNT_INT32,(VOIDP)dim_sca0); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + } + else { + istat = SDsetdimname(dim_id,dim_name1); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,typ_dims[1],DFNT_INT32,(VOIDP)dim_sca1); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + } + + istat = SDsetdimstrs(dim_id,dim_label,dim_unit,dim_format); + if(istat == FAIL) { + printf("sds set dim. predefined attr. failed. \n"); + return FAIL; + } + istat = SDsetattr(dim_id,"sdsdim.attr",DFNT_CHAR8,10,(VOIDP)attr_value); + + if(istat == FAIL) { + printf(" sds dim data attr. setting failed. \n"); + return FAIL; + } + SDendaccess(dim_id); + } + + SDendaccess(sds_id); + + + sds_id = SDcreate(file_id,"sds_compress",DFNT_INT32,TYP_RANK,typ_dims); + if(sds_id == FAIL) { + printf("failed to create object.\n"); + return FAIL; + } + comp_type = COMP_CODE_DEFLATE; + c_info.deflate.level = 3; + + c_def.comp.chunk_lengths[0] = 2; + c_def.comp.chunk_lengths[1] = 2; + c_def.comp.chunk_lengths[2] = 2; + c_def.comp.comp_type = COMP_CODE_DEFLATE; + + comp_flag = HDF_CHUNK; + + c_def.comp.cinfo.deflate.level = 3; + + istat = SDsetchunk(sds_id,c_def,comp_flag); + if(istat == FAIL) { + printf("chunking is not setting properly. \n"); + return FAIL; + } + + + istat = SDwritedata(sds_id,typ_start,typ_stride,typ_edges,(VOIDP)typ_array); + if(istat == FAIL) { + printf("SDS cannot write chunking and compression mode. \n"); + return FAIL; + } + SDendaccess(sds_id); + + SDend(file_id); + free(attr_value); + free(gloattr_value); + return 0; +} + +/***** routines for generating gr datatype hdf testing file. + we are only generating one and three components for + datatype + uint32 and int16. ****/ +int test_grtyp() { + + int32 gr_id, ri_id, file_id, il; + int32 ncomp; + int32 start[2], edges[2],dims[2]; + uint32 image_data32[Y_LENGTH][X_LENGTH][3]; + uint32 image_data321[Y_LENGTH][X_LENGTH]; + int16 image_data16[Y_LENGTH][X_LENGTH][3]; + int16 image_data161[Y_LENGTH][X_LENGTH]; + intn i, j; + int32 CUB_SIZE; + int istat; + + CUB_SIZE = (X_LENGTH-1)*(Y_LENGTH-1); + + /* 3-component GR image data type UINT32*/ + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data32[j][i][0] = UINT32_UPLIMIT - i*j*0/CUB_SIZE*(UINT32_UPLIMIT/2)+1; + image_data32[j][i][1] = UINT32_UPLIMIT - i*j*1/CUB_SIZE*(UINT32_UPLIMIT/2)+1; + image_data32[j][i][2] = UINT32_UPLIMIT - i*j*2/CUB_SIZE*(UINT32_UPLIMIT/2)+1; + + } + } + + /* 3-component GR image data type int16*/ + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data16[j][i][0] = INT16_UPLIMIT - i*j*0/CUB_SIZE*(INT16_UPLIMIT/2)+1; + image_data16[j][i][1] = INT16_UPLIMIT - i*j*1/CUB_SIZE*(INT16_UPLIMIT/2)+1; + image_data16[j][i][2] = INT16_UPLIMIT - i*j*2/CUB_SIZE*(INT16_UPLIMIT/2)+1; + + } + } + + /* 1-component GR image data type uint32 */ + for (j = 0; j < Y_LENGTH; j++) + for (i = 0; i < X_LENGTH; i++) + image_data321[j][i] = UINT32_UPLIMIT - i*j/CUB_SIZE*UINT32_UPLIMIT+1; + + /* 1-component GR image data type int16*/ + for (j = 0; j < Y_LENGTH; j++) + for (i = 0; i < X_LENGTH; i++) + image_data161[j][i] = INT16_UPLIMIT - i*j/CUB_SIZE*INT16_UPLIMIT+1; + + + /* Open the file. */ + file_id = Hopen(FILEGR, DFACC_CREATE, 0); + + if(file_id == FAIL) { + printf("fail to create GR file.\n"); + return FAIL; + } + /* Initiate the GR interface. */ + gr_id = GRstart(file_id); + + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_uint32", ncomp, DFNT_UINT32, il, dims); + + if(ri_id == FAIL) { + printf("fail to create RI interface.\n"); + return FAIL; + } + + /* Define the location, pattern, and size of the data set */ + for (i = 0; i < 2; i++) { + start[i] = 0; + edges[i] = dims[i]; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + /* Terminate access to the image. */ + GRendaccess(ri_id); + + /* For number of components =3, data type is int16*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_int16", ncomp, DFNT_INT16, il, dims); + + if(ri_id == FAIL) { + printf("fail to create RI interface.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data16); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + /* Terminate access to the image. */ + GRendaccess(ri_id); + + /* For number of components =1, data type is uint32*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 1; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_uint321", ncomp, DFNT_UINT32, il, dims); + if(ri_id == FAIL) { + printf("fail to create RI interface.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data321); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + /* Terminate access to the image. */ + GRendaccess(ri_id); + + + /* For number of components = 1, data type is int16*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 1; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_int161", ncomp, DFNT_INT16, il, dims); + + if(ri_id == FAIL) { + printf("fail to create RI interface.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data161); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + /* Terminate access to the image. */ + GRendaccess(ri_id); + /* Terminate access to the GR interface. */ + GRend(gr_id); + + /* Close the file. */ + Hclose(file_id); + return 0; +} + + +/***** routine to generate raster 8 bit data type hdf file. ****/ +int test_ras8() { + + int32 gr_id, ri_id, file_id, il,istat; + int32 ncomp; + int32 start[2], edges[2],dims[2]; + int8 image_data8[Y_LENGTH][X_LENGTH]; + uint8 image_datau8[Y_LENGTH][X_LENGTH]; + intn i, j; + int32 CUB_SIZE; + + CUB_SIZE = (X_LENGTH-1)*(Y_LENGTH-1); + + /* 1-component Raster-8 image data type uint8 */ + for (j = 0; j < Y_LENGTH; j++) + for (i = 0; i < X_LENGTH; i++) + image_datau8[j][i] = UINT8_UPLIMIT - i*j/CUB_SIZE*UINT8_UPLIMIT+1; + + /* 1-component Raster-8 image data type int8*/ + for (j = 0; j < Y_LENGTH; j++) + for (i = 0; i < X_LENGTH; i++) + image_data8[j][i] = INT8_UPLIMIT - i*j/CUB_SIZE*INT8_UPLIMIT+1; + + /* Open the file. */ + file_id = Hopen(FILERAS8, DFACC_CREATE, 0); + + if(file_id == FAIL) { + printf("fail to open raster 8 file.\n"); + return FAIL; + } + /* Initiate the GR interface. */ + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + /* For number of components = 1, data type is uint8*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 1; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_uint8", ncomp, DFNT_UINT8, il, dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_datau8); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Terminate access to the image. */ + istat = GRendaccess(ri_id); + if(istat == FAIL) { + printf("fail in ending RI interface.\n"); + return FAIL; + } + + /* For number of components = 1, data type is int8*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 1; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_int8", ncomp, DFNT_INT8, il, dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data8); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Terminate access to the image. */ + GRendaccess(ri_id); + /* Terminate access to the GR interface. */ + GRend(gr_id); + + /* Close the file. */ + Hclose(file_id); + return 0; +} + +/***** routine to generate raster 24 bit data type hdf file. ****/ +int test_ras24() { + + int32 gr_id, ri_id, file_id, il; + int32 ncomp,istat; + int32 start[2], edges[2],dims[2]; + int8 image_data24[Y_LENGTH][X_LENGTH][3]; + uint8 image_datau24[Y_LENGTH][X_LENGTH][3]; + intn i, j; + int32 CUB_SIZE; + + + CUB_SIZE = (X_LENGTH-1)*(Y_LENGTH-1); + + /* 3-component Raster-8 image data type uint8 */ + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_datau24[j][i][0] = UINT8_UPLIMIT - i*j*0/CUB_SIZE*UINT8_UPLIMIT+1; + image_datau24[j][i][1] = UINT8_UPLIMIT - i*j*1/CUB_SIZE*(UINT8_UPLIMIT/2)+1; + image_datau24[j][i][2] = UINT8_UPLIMIT - i*j*2/CUB_SIZE*(UINT8_UPLIMIT/2)+1; + } + } + /* 3-component Raster-8 image data type int8*/ + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data24[j][i][0] = INT8_UPLIMIT - i*j*0/CUB_SIZE*INT8_UPLIMIT+1; + image_data24[j][i][1] = INT8_UPLIMIT - i*j*1/CUB_SIZE*(INT8_UPLIMIT/2)+1; + image_data24[j][i][2] = INT8_UPLIMIT - i*j*2/CUB_SIZE*(INT8_UPLIMIT/2)+1; + + } + } + + /* Open the file. */ + file_id = Hopen(FILERAS24, DFACC_CREATE, 0); + + if(file_id == FAIL) { + printf("fail to open the file. \n"); + return FAIL; + } + + /* Initiate the GR interface. */ + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + + /* For number of components = 3, data type is uint8*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_uint24", ncomp, DFNT_UINT8, il, dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_datau24); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + /* Terminate access to the image. */ + GRendaccess(ri_id); + + + /* For number of components = 3, data type is int8*/ + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_int24", ncomp, DFNT_INT8, il, dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data24); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Terminate access to the image. */ + GRendaccess(ri_id); + /* Terminate access to the GR interface. */ + GRend(gr_id); + + /* Close the file. */ + Hclose(file_id); + return 0; +} + +/* routine to generate image attribute file.*/ +int test_imageattr() { + + int32 gr_id, ri_id, file_id, il,pal_id,istat; + int32 ncomp,data_type; + int32 start[2], edges[2],dims[2]; + uint16 image_data[Y_LENGTH][X_LENGTH][3]; + + uint8 palette_data[NUM_COLORS * 3]; + int32 num_comp,num_entries; + intn i, j; + char* ri_attrname; + char*file_attrname; + + /* Open the file. */ + file_id = Hopen(FILEGRPAL, DFACC_CREATE, 0); + + /* Initiate the GR interface. */ + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + dims[0] = X_LENGTH; + dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_1", ncomp, DFNT_UINT16, il, dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + /* Fill the stored-data array with values. */ + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data[j][i][0] = i+j+1; + image_data[j][i][1] = (i+j)*2; + image_data[j][i][2] = (i+j)*3; + } + } + + /* Define the location, pattern, and size of the data set */ + for (i = 0; i < 2; i++) { + start[i] = 0; + edges[i] = dims[i]; + } + + /* set GR global attribute. */ + + file_attrname=malloc(strlen(F_ATT1_NAME)); + strcpy(file_attrname,F_ATT1_NAME); + istat = GRsetattr(gr_id,file_attrname,DFNT_CHAR8,F_ATT1_N_VALUES,(VOIDP)F_ATT1_VAL); + if(istat == FAIL) { + printf("fail to set GR global attribute.\n"); + return FAIL; + } + /* set GR attribute. */ + ri_attrname=malloc(strlen(RI_ATT1_NAME)); + strcpy(ri_attrname,RI_ATT1_NAME); + istat = GRsetattr(ri_id,ri_attrname,DFNT_CHAR8,RI_ATT1_N_VALUES,(VOIDP)RI_ATT1_VAL); + if(istat == FAIL) { + printf("fail to set GR attribute.\n"); + return FAIL; + } + free(file_attrname); + free(ri_attrname); + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Initialize the palette to grayscale. */ + for (i = 0; i < NUM_COLORS; i++) { + palette_data[i * 3] = i; + palette_data[i * 3 + 1] = i; + palette_data[i * 3 + 2] = i; + } + + /* Set palette characteristics. */ + data_type = DFNT_UINT8; + num_entries = NUM_COLORS; + num_comp = 3; + + /* Get the id for the palette. */ + pal_id = GRgetlutid(ri_id,0 ); + if(pal_id == FAIL) { + printf("fail to obtain palette id.\n"); + return FAIL; + } + + /* Write the palette to file. */ + istat = GRwritelut(pal_id, num_comp, data_type, + 0, num_entries, + (VOIDP)palette_data); + if(istat == FAIL) { + printf("fail to write lookup table.\n"); + return FAIL; + } + + /* Terminate access to the image. */ + GRendaccess(ri_id); + + /* Terminate access to the GR interface. */ + GRend(gr_id); + + /* Close the file. */ + Hclose(file_id); + return 0; +} + +/* routines to generate vdata hdf testing file. */ +int test_vdata( ) +{ + + struct { + float32 temp; + int16 height; + float32 speed; + char ident[3]; + float32 position[2]; + } source[NRECORDS]; + + int32 file_id, vdata_id, istat, values[4] ={32, 16, 32, 8}; + uint8 *databuf, *pntr; + int i,j, bufsize, recsize; + VOIDP fldbufpt[5]; + + /* Open the HDF file. */ + file_id = Hopen(FILEVD, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open HDF file.\n"); + return FAIL; + } + + /* Initialize the Vset interface. */ + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start V interface.\n"); + return FAIL; + } + + /* Create a new Vdata. */ + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach Vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define field1 \n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define field2 \n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_3, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define field3 \n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_4, DFNT_CHAR8, 3); + if(istat == FAIL) { + printf("fail to define field4 \n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_5, DFNT_FLOAT32,2); + if(istat == FAIL) { + printf("fail to define field5 \n"); + return FAIL; + } + + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name\n"); + return FAIL; + } + + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class\n"); + return FAIL; + } + + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_NAMES); + if(istat == FAIL) { + printf("fail to set fields of vdata.\n"); + return FAIL; + } + + recsize = (2 * sizeof(float32) + sizeof(int16))+ 2* sizeof(float32) + +3*sizeof(char); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc memory for vdata failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + source[i].speed = 1.11 * (i+1); + source[i].ident[0] = 'A' + i; + source[i].ident[1] = 'a' + i; + source[i].ident[2] ='0'+i; + for (j=0; j< 2; j++) + source[i].position[j] = 1.0+j; + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + fldbufpt[2] = &source[i].speed; + fldbufpt[3] = &source[i].ident[0]; + fldbufpt[4] = &source[i].position[0]; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + /* Set Vdata attribute */ + istat = VSsetattr (vdata_id, _HDF_VDATA, "vdata attr", DFNT_INT32, 4, (VOIDP)values); + if(istat == FAIL) { + printf("fail to set vdata attribute.\n"); + return FAIL; + } + /* Set attribute for "speed" field */ + istat = VSsetattr (vdata_id, 2, "field attr", DFNT_CHAR, 3, "MAX"); + if(istat == FAIL) { + printf("fail to set vdata field attribute.\n"); + return FAIL; + } + /* + * Terminate access to the Vdata, the Vset interface + * and the HDF file. + */ + VSdetach(vdata_id); + Vend(file_id); + Hclose(file_id); + free(databuf); + return 0; +} + +/* this routine will generate hdf file that has name clashings for different + vgroups. + + two situations: + 1. two groups share the same name. + 2. one group doesn't have name. + + */ +int test_vgnameclash() { + + int32 file_id, vgroupa_ref, vgroupa_id,vgroupb_ref,vgroupb_id; + int32 vgroupc_id,vgroupc_ref; + int32 dim_sizes[TYP_RANK]; + intn i, j; + int32 sd_id,sds_id; + int32 sds_ref; + int32 array_data[X_LENGTH][Y_LENGTH]; + int32 start[TYP_RANK],edges[TYP_RANK],stride[TYP_RANK]; + int istat; + + for (i=0;i<X_LENGTH;i++){ + for(j=0;j<Y_LENGTH;j++) { + array_data[i][j] =i+j; + } + } + + dim_sizes[0] = X_LENGTH; + dim_sizes[1] = Y_LENGTH; + + for (i=0;i<TYP_RANK;i++){ + stride[i]=1; + start[i]=0; + edges[i]=dim_sizes[i]; + + } + + /* Open the HDF file. */ + + /* We are testing name clashings for vgroups.*/ + + /* two situations: + 1. two groups share the same name. + 2. one group doesn't have name. */ + + file_id = Hopen(FILECLASHVG, DFACC_CREATE, 0); + if (file_id == FAIL) { + printf("fail to open vg_clash.hdf.\n"); + return FAIL; + } + + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vgroup interface.\n"); + return FAIL; + } + vgroupa_ref = -1; + vgroupb_ref = -1; + vgroupc_ref = -1; + vgroupa_id = Vattach(file_id, vgroupa_ref, "w"); + if(vgroupa_id == FAIL) { + printf("fail to attach groupa.\n"); + return FAIL; + } + vgroupb_id = Vattach(file_id,vgroupb_ref,"w"); + if(vgroupb_id == FAIL) { + printf("fail to attach groupb.\n"); + return FAIL; + } + vgroupc_id = Vattach(file_id,vgroupc_ref,"w"); + if(vgroupc_id == FAIL) { + printf("fail to attach groupc.\n"); + return FAIL; + } + istat=Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + + istat=Vsetname(vgroupb_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupb.\n"); + return FAIL; + } + sd_id = SDstart(FILECLASHVG,DFACC_WRITE); + if(sd_id == FAIL) { + printf("fail to start SD interface.\n"); + return FAIL; + } + + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupa_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + + SDendaccess(sds_id); + SDend(sd_id); + Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + istat = Vdetach(vgroupc_id); + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} + +/* This routine creates different SDS objects with name clashing. +We are testing different SDS + 1. under the same group sharing the same name. + 2. one sds doesn't have name. + 3. different sds objects under different vgroups sharing the same name. + 4. sds objects under no specific groups share the same name. + 5. sds objects under no specific groups with no name. */ + + +int test_sdsnameclash() { + + + int32 file_id, vgroupa_ref, vgroupa_id,vgroupb_ref,vgroupb_id; + int32 dim_sizes[TYP_RANK]; + int32 vgroupc_ref,vgroupc_id; + intn i, j,istat; + int32 sd_id,sds_id; + int32 sds_ref; + int32 array_data[X_LENGTH][Y_LENGTH]; + int32 start[TYP_RANK],edges[TYP_RANK],stride[TYP_RANK]; + + + for (i=0;i<X_LENGTH;i++){ + for(j=0;j<Y_LENGTH;j++) { + array_data[i][j] =i+j; + } + } + + dim_sizes[0] = X_LENGTH; + dim_sizes[1] = Y_LENGTH; + + for (i=0;i<TYP_RANK;i++){ + stride[i]=1; + start[i]=0; + edges[i]=dim_sizes[i]; + + } + + /* Open the HDF file. */ + + file_id = Hopen(FILECLASHSDS, DFACC_CREATE, 0); + istat = Vstart(file_id); + vgroupa_ref = -1; + vgroupb_ref = -1; + vgroupc_ref = -1; + vgroupa_id = Vattach(file_id,vgroupa_ref,"w"); + if(vgroupa_id == FAIL) { + printf("fail to attach groupa.\n"); + return FAIL; + } + vgroupb_id = Vattach(file_id,vgroupb_ref,"w"); + if(vgroupb_id == FAIL) { + printf("fail to attach groupb.\n"); + return FAIL; + } + vgroupc_id = Vattach(file_id,vgroupc_ref,"w"); + if(vgroupc_id == FAIL) { + printf("fail to attach groupc.\n"); + return FAIL; + } + istat=Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + istat=Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set name for groupb.\n"); + return FAIL; + } + Vsetname(vgroupc_id,"groupC"); + if(istat == FAIL) { + printf("fail to set name for groupc.\n"); + return FAIL; + } + sd_id = SDstart(FILECLASHSDS,DFACC_WRITE); + if(sd_id == FAIL) { + printf("fail to start SD interface.\n"); + return FAIL; + } + /* putting one sds object under groupa. */ + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + /* a sds object with the name "sds" is put under group a.*/ + istat = Vaddtagref(vgroupa_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + SDendaccess(sds_id); + + /* putting another sds with the same same "sds" under groupa. + It is legal for hdf lib. */ + + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupa_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + + SDendaccess(sds_id); + + /* no sds name is given under groupc*/ + sds_id = SDcreate(sd_id,NULL,DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupc_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + + SDendaccess(sds_id); + + /* another no name sds object is put under group c. */ + sds_id = SDcreate(sd_id,NULL,DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupc_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + SDendaccess(sds_id); + + /* another sds with the same name under groupb is given.*/ + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("failed to transfer sds id to reference number.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupb_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add tag for reference.\n"); + return FAIL; + } + SDendaccess(sds_id); + + /* two sds share the same name under no specific groups.*/ + sds_id = SDcreate(sd_id,"sds_independent",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + sds_id = SDcreate(sd_id,"sds_independent",DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + /* another sds with no name and is not tagged with any group. */ + sds_id = SDcreate(sd_id,NULL,DFNT_INT32,2,dim_sizes); + if(sds_id == FAIL) { + printf("failed to create sds object.\n"); + return FAIL; + } + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("failed to write sds data. \n"); + return FAIL; + } + SDendaccess(sds_id); + + SDend(sd_id); + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + istat = Vdetach(vgroupc_id); + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} + +/*A routine to generate a testing file that deals with different +name clashings for image. +We are testing different Image + 1. under the same group sharing the same name. + 2. one image doesn't have name(not allowed) + 3. different image objects under different vgroups sharing the same name. + 4. image objects under no specific groups share the same name. + 5. image objects under no specific groups with no name(not allowed). */ + + +int test_grnameclash() { + + + int32 file_id, vgroupa_ref, vgroupa_id,vgroupb_ref,vgroupb_id,istat; + int32 dim_sizes[2]; + + int i, j; + int32 gr_id,ri_id,il,ncomp; + int32 gr_ref; + int32 start[2], edges[2]; + uint32 image_data32[Y_LENGTH][X_LENGTH][3]; + + for (j=0;j<Y_LENGTH;j++){ + for(i=0;i<X_LENGTH;i++) { + image_data32[j][i][0] = i; + image_data32[j][i][1] = j; + image_data32[j][i][2] = i+j; + } + } + + dim_sizes[0] = X_LENGTH; + dim_sizes[1] = Y_LENGTH; + + + /* Open the HDF file. */ + + file_id = Hopen(FILECLASHGR, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open the file.\n"); + return FAIL; + } + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vgroup interface.\n"); + return FAIL; + } + vgroupa_ref = -1; + vgroupb_ref = -1; + + vgroupa_id = Vattach(file_id,vgroupa_ref,"w"); + if(vgroupa_id == FAIL) { + printf("fail to attach groupa.\n"); + return FAIL; + } + vgroupb_id = Vattach(file_id,vgroupb_ref,"w"); + if(vgroupb_id == FAIL) { + printf("fail to attach groupb.\n"); + return FAIL; + } + + istat=Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + + istat=Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set name for groupb.\n"); + return FAIL; + } + + gr_id = GRstart(file_id); + + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + /* Define the location, pattern, and size of the data set */ + for (i = 0; i < 2; i++) { + start[i] = 0; + edges[i] = dim_sizes[i]; + } + /* Define the number of components and dimensions of the image. */ + ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + + /* Create the array. */ + /* 1.1. put one image with the name "Imagea" under groupa.*/ + ri_id = GRcreate(gr_id, "Imagea", ncomp, DFNT_UINT32, il, dim_sizes); + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + gr_ref = GRidtoref(ri_id); + if(gr_ref == FAIL) { + printf("fail to convert ri_id into reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupa_id,DFTAG_RIG,gr_ref); + if(istat == FAIL) { + printf("fail to add gr object into vgroup a.\n"); + return FAIL; + } + GRendaccess(ri_id); + + /* 1.2 putting the same same image object under groupa. */ + /* Create the array. */ + ri_id = GRcreate(gr_id, "Imagea", ncomp, DFNT_UINT32, il, dim_sizes); + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + gr_ref = GRidtoref(ri_id); + if(gr_ref == FAIL) { + printf("fail to convert ri_id into reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupa_id,DFTAG_RIG,gr_ref); + if(istat == FAIL) { + printf("fail to add gr object into vgroup a.\n"); + return FAIL; + } + GRendaccess(ri_id); + + + /* 2.0 no image name is given, it is illegal for hdf4 lib; therefore; + no test cases are given. */ + + + /* 3.1 another image with the "imagea" under groupb is given.*/ + ri_id = GRcreate(gr_id,"imagea", ncomp, DFNT_UINT32, il, dim_sizes); + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + gr_ref = GRidtoref(ri_id); + if(gr_ref == FAIL) { + printf("fail to convert ri_id into reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupb_id,DFTAG_RIG,gr_ref); + if(istat == FAIL) { + printf("fail to add gr object into vgroup a.\n"); + return FAIL; + } + GRendaccess(ri_id); + + /* 4.0 two images share the same name under no specific groups.*/ + + ri_id = GRcreate(gr_id, "Image_independent", ncomp, DFNT_UINT32, il, dim_sizes); + + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + GRendaccess(ri_id); + + ri_id = GRcreate(gr_id, "Image_independent", ncomp, DFNT_UINT32, il, dim_sizes); + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, start, NULL, edges, (VOIDP)image_data32); + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + GRendaccess(ri_id); + GRend(gr_id); + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} +/* a routine that generates the name clashing for vdata object. some + redundant codes can found in this routine, it should be corrected later. + + Cases: + + 1. two independent Vdata with the same name not under any user-specified group. + 2. vdata without any names and not under any user-specified groups. + 3. different Vdata objects under the same vgroup sharing the same name. + 4. different Vdata objects under different vgroups sharing the same name. + 5. Vdata without any names under one user-specified group*/ + +int test_vdnameclash() { + + int32 file_id, vgroupa_ref, vgroupa_id,vgroupb_ref,vgroupb_id; + int32 vgroupc_id,vgroupc_ref,vd_ref; + + struct { + float32 temp; + int16 height; + } source[NRECORDS]; + + int32 vdata_id, istat; + uint8 *databuf, *pntr; + int i, bufsize, recsize; + VOIDP fldbufpt[2]; + + /* Open the HDF file. */ + file_id = Hopen(FILECLASHVD, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open the file.\n"); + return FAIL; + } + /* Initialize the Vset interface. */ + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vgroup interface.\n"); + return FAIL; + } + + /* 1.0 + Create an independent new Vdata with the name "Test Vset Name". */ + + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata id.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("fail to allocate memory for databuf"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + + free(databuf); + VSdetach(vdata_id); + + /* 1.1 + Create another independent Vdata with the name "Test Vset Name" */ + + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + free(databuf); + VSdetach(vdata_id); + + /* An independent Vdata without name not under any user-specified vgroup. */ + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata id.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + /* Set the Vdata class. + istat=VSsetclass(vdata_id, "Test Vset Class");*/ + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + free(databuf); + VSdetach(vdata_id); + + vgroupa_ref = -1; + vgroupb_ref = -1; + vgroupc_ref = -1; + + /* 3. two vdata with the same name under groupa. */ + vgroupa_id = Vattach(file_id, vgroupa_ref,"w"); + + Vsetname(vgroupa_id,"groupA"); + /* Create a new Vdata. */ + vdata_id = VSattach(file_id, -1, "w"); + + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name. \n"); + return FAIL; + } + + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + free(databuf); + vd_ref = VSQueryref(vdata_id); + if(vd_ref == FAIL) { + printf("fail to query vdata.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupa_id,DFTAG_VH,vd_ref); + if(istat == FAIL){ + printf("fail to add vdata into vgroup.\n"); + return FAIL; + } + VSdetach(vdata_id); + + /* Create a new Vdata. */ + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + free(databuf); + vd_ref = VSQueryref(vdata_id); + if(vd_ref== FAIL) { + printf("fail to query reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupa_id,DFTAG_VH,vd_ref); + if(istat == FAIL) { + printf("fail to add vdata into vgroup a.\n"); + return FAIL; + } + VSdetach(vdata_id); + + + /*4. another vdata with the same name under groupb.*/ + vgroupb_id = Vattach(file_id,vgroupb_ref,"w"); + if(vgroupb_id == FAIL) { + printf("fail to attach vgroup b.\n"); + return FAIL; + } + + istat=Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set group b name.\n"); + return FAIL; + } + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + /* Set the Vdata name. */ + istat=VSsetname(vdata_id, "Test Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + /* Set the Vdata class. */ + istat=VSsetclass(vdata_id, "Test Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + + free(databuf); + vd_ref = VSQueryref(vdata_id); + if(vd_ref == FAIL) { + printf("fail to query reference.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupb_id,DFTAG_VH,vd_ref); + if(istat == FAIL) { + printf("fail to add vdata into vgroup.\n"); + return FAIL; + } + + VSdetach(vdata_id); + + /* 5. vdata without name under groupc. */ + vgroupc_id = Vattach(file_id,vgroupc_ref,"w"); + if(vgroupc_id == FAIL) { + printf("fail to attach vgroup c.\n"); + return FAIL; + } + istat = Vsetname(vgroupc_id,"groupC"); + if(istat == FAIL) { + printf("fail to set group c name.\n"); + return FAIL; + } + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_VDNAMES); + if(istat == FAIL) { + printf("fail to set field name.\n"); + return FAIL; + } + + recsize = sizeof(float32) + sizeof(int16); + + bufsize = recsize * NRECORDS; + databuf = (uint8 *) malloc((size_t)bufsize); + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + + } + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + + free(databuf); + vd_ref = VSQueryref(vdata_id); + if(vd_ref == FAIL) { + printf("fail to get reference number for vata.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupc_id,DFTAG_VH,vd_ref); + if(istat == FAIL) { + printf("fail to add vdata into groupc.\n"); + return FAIL; + } + VSdetach(vdata_id); + + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + istat = Vdetach(vgroupc_id); + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} + +/* a routine that generates a hdf file with vgroup loops.va->vb 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;i<TYP_DIMSIZE;i++){ + for(j=0;j<TYP_DIMSIZE;j++) { + for(k=0;k<TYP_DIMSIZE;k++){ + array_data[i][j][k] =i+j; + } + } + } + + dims[0] = TYP_DIMSIZE; + dims[1] = TYP_DIMSIZE; + dims[2] = TYP_DIMSIZE; + for (i=0;i<TYP_RANK;i++){ + stride[i]=1; + start[i]=0; + edges[i]=dims[i]; + + } + + /* Open the HDF file. */ + + file_id = Hopen(FILELOOP, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open the file.\n"); + return FAIL; + } + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vdata interface.\n"); + return FAIL; + } + + vgroupa_ref = -1; + vgroupb_ref = -1; + vgroupa_id = Vattach(file_id, vgroupa_ref, "w"); + if(vgroupa_id == FAIL) { + printf("fail to attach group a.\n"); + return FAIL; + } + vgroupb_id = Vattach(file_id, vgroupb_ref, "w"); + if(vgroupb_id == FAIL) { + printf("fail to attach groupb.\n"); + return FAIL; + } + istat = Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + istat = Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + istat = Vinsert(vgroupa_id,vgroupb_id); + if(istat == FAIL) { + printf("fail to insert groupb into groupa.\n"); + return FAIL; + } + + istat = Vinsert(vgroupb_id,vgroupa_id); + if(istat == FAIL) { + printf("fail to insert groupa into groupb.\n"); + return FAIL; + } + sd_id = SDstart(FILELOOP,DFACC_WRITE); + if(sd_id == FAIL) { + printf("fail to start sd interface.\n"); + return FAIL; + } + + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,TYP_RANK,dims); + if(sds_id == FAIL) { + printf("fail to create sds interface.\n"); + return FAIL; + } + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("fail to write sds data.\n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("fail to create sds reference.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupa_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add sds into vgroupa\n"); + return FAIL; + } + SDendaccess(sds_id); + SDend(sd_id); + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} + +/* a routine that creates a hdf file which has one sds under two + different vgroups. */ +int test_vghl() { + + 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;i<TYP_DIMSIZE;i++){ + for(j=0;j<TYP_DIMSIZE;j++) { + for(k=0;k<TYP_DIMSIZE;k++){ + array_data[i][j][k] =i+j; + } + } + } + + dims[0] = TYP_DIMSIZE; + dims[1] = TYP_DIMSIZE; + dims[2] = TYP_DIMSIZE; + for (i=0;i<TYP_RANK;i++){ + stride[i]=1; + start[i]=0; + edges[i]=dims[i]; + + } + + /* Open the HDF file. */ + + file_id = Hopen(FILEHL, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open hdf file.\n"); + return FAIL; + } + + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vdata interface.\n"); + return FAIL; + } + vgroupa_ref = -1; + vgroupb_ref = -1; + vgroupa_id = Vattach(file_id, vgroupa_ref, "w"); + if(vgroupa_id == FAIL) { + printf("fail to attach group a.\n"); + return FAIL; + } + vgroupb_id = Vattach(file_id, vgroupb_ref, "w"); + if(vgroupb_id == FAIL) { + printf("fail to attach groupb.\n"); + return FAIL; + } + istat = Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + istat = Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + sd_id = SDstart(FILEHL,DFACC_WRITE); + if(sd_id == FAIL) { + printf("fail to start sd interface.\n"); + return FAIL; + } + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,TYP_RANK,dims); + if(sds_id == FAIL) { + printf("fail to create sds interface.\n"); + return FAIL; + } + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("fail to write sds data.\n"); + return FAIL; + } + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("fail to create sds reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupa_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add sds into vgroupa\n"); + return FAIL; + } + istat = Vaddtagref(vgroupb_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add sds into vgroupb\n"); + return FAIL; + } + SDendaccess(sds_id); + SDend(sd_id); + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupb_id); + istat = Vend(file_id); + istat = Hclose(file_id); + return 0; +} +/* this is a comprehensive testing file for h4-h5 converter. It includes + annotation,vdata,image,sds,palette and vgroup objects*/ +/* the structure of the hdf5 file is as follows: + root + / \ + gc ga<-- + / \ | + gd gb-- + / + ge + + This file includes vdata,image and sds. + +*/ +int test_vgall() { + + typedef struct { + float32 temp; + int16 height; + float32 speed; + char ident; + float32 position[2]; + } source_t; + + source_t source[NRECORDS]; + + int32 file_id, vgroupa_ref, vgroupa_id,istat; + int32 vgroupc_ref, vgroupc_id,vgroupb_ref,vgroupb_id; + int32 vgroupd_ref, vgroupd_id,vgroupe_ref,vgroupe_id; + int32 vdata_id,values[4]={32, 16, 32, 8}; + + intn i, j,k; + + uint8 *databuf, *pntr; + int bufsize, recsize; + VOIDP fldbufpt[5]; + + /*2. for sds */ + int32 sd_id,sds_id,dim_id; + int32 sds_ref; + int32 fill_value; + int32 array_data[TYP_DIMSIZE][TYP_DIMSIZE][TYP_DIMSIZE]; + int32 dimo_sca[TYP_DIMSIZE]; + int32 dim_sizes[TYP_RANK]; + int32 start[TYP_RANK],edges[TYP_RANK],stride[TYP_RANK]; + float64 cal; + float64 cal_err; + float64 offset; + float64 offset_err; + + /*3. for image. */ + + int32 gr_id, ri_id, il,pal_id; + int32 image_ncomp,image_data_type; + int32 image_start[2], image_edges[2],image_dims[2]; + int16 image_data[Y_LENGTH][X_LENGTH][3]; + uint8 palette_data[NUM_COLORS*3]; + int32 image_num_comp; + int32 image_num_entries; + int32 image_ref; + + char* attr_value; + + /*4. for annotation. */ + int32 an_id,ann_id; + int32 group_tag,group_ref; + + static char file_label[] = "This is a file label."; + static char file_desc[] = "This is a file description."; + static char data_label[] = "This is a data label."; + static char data_desc[] = "This is a data description."; + + char label[] = "sds.label"; + char unit[] = "sds.unit"; + char format[] = "sds.format"; + char coordsys[] = "sds.coord"; + + char dim_name0[] ="dim0"; + char dim_name1[] ="dim1"; + char dim_label[] ="dim.label"; + char dim_unit[] ="dim.unit"; + char dim_format[] ="dim.format"; + + /**** initial setting. ****/ + cal = 1.0; + cal_err = 0.0; + offset = 0.0; + offset_err = 0.0; + fill_value = 999; + + attr_value = malloc(ATT_SIZE*sizeof(char)); + if(attr_value == NULL) { + printf("fail to allocate memory.\n"); + return FAIL; + } + strcpy(attr_value,"test attr"); + + for (i=0;i<TYP_DIMSIZE;i++){ + for(j=0;j<TYP_DIMSIZE;j++) { + for(k=0;k<TYP_DIMSIZE;k++) { + array_data[i][j][k]=i+j; + } + } + } + + for (i=0;i<TYP_DIMSIZE;i++) + dimo_sca[i]= 2*i; + + for (i=0;i<TYP_RANK;i++){ + stride[i]=1; + start[i]=0; + dim_sizes[i] = TYP_DIMSIZE; + edges[i]=dim_sizes[i]; + + } + + /* Open the HDF file. */ + + file_id = Hopen(FILEVG, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open the file.\n"); + return FAIL; + } + + /* create annotations. */ + + /* Initialize the AN interface and obtain an interface id. */ + an_id = ANstart(file_id); + if(an_id == FAIL) { + printf("fail to start annotation interface.\n"); + return FAIL; + } + /* Create a file label and obtain an annotation id. */ + ann_id = ANcreatef(an_id, AN_FILE_LABEL); + if(ann_id == FAIL) { + printf("fail to create file annotion interface.\n"); + return FAIL; + } + + /* Write the file label to the file. */ + istat = ANwriteann(ann_id, file_label, (int32)(strlen(file_label))); + if(istat == FAIL) { + printf("fail to write file annotation.\n"); + return FAIL; + } + + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Create a file description. */ + ann_id = ANcreatef(an_id, AN_FILE_DESC); + if(ann_id == FAIL) { + printf("fail to create file annotion interface.\n"); + return FAIL; + } + /* Write the file description to the file. */ + istat = ANwriteann(ann_id, file_desc, (int32)(strlen(file_desc))); + if(istat == FAIL) { + printf("fail to write file annotation.\n"); + return FAIL; + } + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Initialize the Vset interface. */ + + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start vdata interface.\n"); + return FAIL; + } + /** Create Vgroup VA and VB***/ + vgroupa_ref = -1; + vgroupb_ref = -1; + + /* Attach to the target vgroup. */ + vgroupa_id = Vattach(file_id, vgroupa_ref, "w"); + if(vgroupa_id == FAIL) { + printf("fail to attach group a.\n"); + return FAIL; + } + istat=Vsetname(vgroupa_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupa.\n"); + return FAIL; + } + /* Attach an attribute to the vgroup. */ + + istat = Vsetattr(vgroupa_id,"vgattr",DFNT_CHAR,5,"TESTa"); + if(istat == FAIL) { + printf("fail to set attribute.\n"); + return FAIL; + } + + vgroupb_id = Vattach(file_id,vgroupb_ref,"w"); + if(vgroupb_id == FAIL) { + printf("fail to attach group b.\n"); + return FAIL; + } + Vsetname(vgroupb_id,"groupB"); + if(istat == FAIL) { + printf("fail to set name for groupb.\n"); + return FAIL; + } + /* adding annotation into the file. */ + group_tag = VQuerytag(vgroupb_id); + if(group_tag == FAIL) { + printf("query groupb tag failed.\n"); + return FAIL; + } + group_ref = VQueryref(vgroupb_id); + if(group_ref == FAIL) { + printf("query groupb ref failed.\n"); + return FAIL; + } + + /* Create a data label for the Vgroup just created. */ + ann_id = ANcreate(an_id, (uint16)group_tag,(uint16)group_ref, AN_DATA_LABEL); + if(ann_id == FAIL) { + printf("AN create interface failed.\n"); + return FAIL; + } + + /* Write the data label to the file. */ + istat = ANwriteann(ann_id, data_label, (int32)(strlen(data_label))); + if(istat == FAIL) { + printf("fail to write annotation.\n"); + return FAIL; + } + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Create a data description for the Vgroup just created.*/ + ann_id = ANcreate(an_id, (uint16)group_tag, (uint16)group_ref, AN_DATA_DESC); + if(ann_id == FAIL) { + printf("AN create interface failed.\n"); + return FAIL; + } + /* Write the data description to the file. */ + istat = ANwriteann(ann_id, data_desc, (int32)(strlen(data_desc))); + if(istat == FAIL) { + printf("fail to write annotation.\n"); + return FAIL; + } + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Terminate access to the AN interface. */ + istat = ANend(an_id); + /* end of annotations. */ + + istat = Vsetattr(vgroupb_id, VGATTR_NAME, DFNT_CHAR, 5, "TESTb"); + if(istat == FAIL) { + printf("fail to set attribute.\n"); + return FAIL; + } + istat = Vinsert(vgroupa_id,vgroupb_id); + if(istat == FAIL) { + printf("fail to insert groupb into groupa. \n"); + return FAIL; + } + + vgroupc_ref = -1; + vgroupd_ref = -1; + vgroupe_ref = -1; + vgroupc_id = Vattach(file_id,vgroupc_ref,"w"); + if(vgroupc_id == FAIL) { + printf("fail to attach groupc into file.\n"); + return FAIL; + } + + istat= Vsetname(vgroupc_id,"groupA"); + if(istat == FAIL) { + printf("fail to set name for groupA.\n"); + return FAIL; + } + + vgroupd_id = Vattach(file_id,vgroupd_ref,"w"); + if(vgroupd_id == FAIL) { + printf("fail to attach groupd into the file.\n"); + return FAIL; + } + + istat= Vsetname(vgroupd_id,"groupD"); + if(istat == FAIL) { + printf("fail to set name for groupD.\n"); + return FAIL; + } + vgroupe_id = Vattach(file_id,vgroupe_ref,"w"); + if(vgroupe_id == FAIL) { + printf("fail to attach groupe into the file.\n"); + return FAIL; + } + istat=Vsetname(vgroupe_id,"groupE"); + if(istat == FAIL) { + printf("fail to set name for groupD.\n"); + return FAIL; + } + istat = Vinsert(vgroupc_id,vgroupd_id); + if(istat == FAIL) { + printf("fail to insert groupd into groupc.\n"); + return FAIL; + } + + istat = Vinsert(vgroupd_id,vgroupe_id); + if(istat == FAIL) { + printf("fail to insert groupe into groupd.\n"); + return FAIL; + } + istat = Vinsert(vgroupe_id,vgroupc_id); + if(istat == FAIL) { + printf("fail to insert groupc into groupe.\n"); + return FAIL; + } + /* Create a new Vdata. */ + + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata.\n"); + return FAIL; + } + /* Define the field to write. */ + + istat = VSfdefine(vdata_id, FIELD_1, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 1.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_2, DFNT_INT16, 1); + if(istat == FAIL) { + printf("fail to define vdata field 2.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_3, DFNT_FLOAT32, 1); + if(istat == FAIL) { + printf("fail to define vdata field 3.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_4, DFNT_CHAR8, 1); + if(istat == FAIL) { + printf("fail to define vdata field 4.\n"); + return FAIL; + } + istat = VSfdefine(vdata_id, FIELD_5, DFNT_FLOAT32,2); + if(istat == FAIL) { + printf("fail to define vdata field 5.\n"); + return FAIL; + } + /* Set the Vdata name. */ + istat = VSsetname(vdata_id, "Example Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + /* Set the Vdata class. */ + istat = VSsetclass(vdata_id, "Example Vset Class"); + if(istat == FAIL) { + printf("fail to set vdata class.\n"); + return FAIL; + } + /* Set the field names. */ + istat = VSsetfields(vdata_id, FIELD_NAMES); + if(istat == FAIL) { + printf("fail to set fields.\n"); + return FAIL; + } + recsize = (2 * sizeof(float32) + sizeof(int16)) +2* sizeof(float32) + +sizeof(char); + /********************debugging *********************/ + /* + sizeof(char)); */ + + bufsize = recsize * NRECORDS; + + databuf = (uint8 *) malloc((size_t)bufsize); + + if (databuf == NULL) { + printf("malloc failed\n"); + return FAIL; + } + pntr = databuf; + + /* set record values */ + for (i = 0; i < NRECORDS; i++) { + source[i].temp = 1.11 * (i+1); + source[i].height = i; + source[i].speed = 1.11 * (i+1); + source[i].ident = 'A' + i; + for (j=0; j< 2; j++) + source[i].position[j] = 1.0+j; + + } + + /* pack one record at a time */ + for (i = 0; i< NRECORDS; i++) { + /* set field buf address */ + fldbufpt[0] = &source[i].temp; + fldbufpt[1] = &source[i].height; + fldbufpt[2] = &source[i].speed; + fldbufpt[3] = &source[i].ident; + fldbufpt[4] = &source[i].position[0]; + /* pack field data into databuf */ + istat = VSfpack(vdata_id,_HDF_VSPACK,NULL,(VOIDP)pntr, + recsize, 1, NULL, fldbufpt); + if (istat == FAIL) { + printf("VSfpack failed in packing record %d\n", i); + return FAIL; + } + pntr = pntr + recsize; + } + + /* Write the data to the Vset object. */ + istat = VSwrite(vdata_id, databuf, NRECORDS, FULL_INTERLACE); + if(istat == FAIL) { + printf("fail to write vdata.\n"); + return FAIL; + } + /* Set Vdata attribute */ + istat = VSsetattr (vdata_id, _HDF_VDATA, "Fixed_type", DFNT_INT32, 4, + (VOIDP)values); + if(istat == FAIL) { + printf("fail to set vdata attribute.\n"); + return FAIL; + } + /* Set attribute for "speed" field */ + istat = VSsetattr (vdata_id, 2, "Symbol", DFNT_CHAR, 3, "MAX"); + if(istat == FAIL) { + printf("fail to set speed attribute.\n"); + return FAIL; + } + + istat = VSdetach(vdata_id); + if(istat == FAIL) { + printf("fail to detach vdata.\n"); + return FAIL; + } + + /*** initialize another empty vdata set to test name clashings ***/ + + vdata_id = VSattach(file_id, -1, "w"); + if(vdata_id == FAIL) { + printf("fail to attach vdata_id into file_id.\n"); + return FAIL; + } + + /* Set the Vdata name. */ + + istat = VSsetname(vdata_id, "Example Vset Name"); + if(istat == FAIL) { + printf("fail to set vdata name.\n"); + return FAIL; + } + istat = VSdetach(vdata_id); + if(istat == FAIL) { + printf("fail to detach vdata.\n"); + return FAIL; + } + + /* Initialize an independent Image interface. */ + /************************************************/ + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + image_ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + image_dims[0] = X_LENGTH; + image_dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_1", image_ncomp, DFNT_INT16, il, + image_dims); + if(ri_id == FAIL) { + printf("fail to create GR object.\n"); + return FAIL; + } + + /* Fill the stored-data array with values. */ + + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data[j][i][0] = (i + j) + 1; + image_data[j][i][1] = (i + j) + 1; + image_data[j][i][2] =(i+j)+1; + } + } + + /* Define the location, pattern, and size of the data set */ + + for (i = 0; i < 2; i++) { + image_start[i] = 0; + image_edges[i] = image_dims[i]; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, image_start, NULL, image_edges, + (VOIDP)image_data); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Initialize the palette to grayscale. */ + for (i = 0; i < NUM_COLORS; i++) { + palette_data[i * 3] = i; + palette_data[i * 3 + 1] = i; + palette_data[i * 3 + 2] = i; + } + + /* Set palette characteristics. */ + + image_data_type = DFNT_UINT8; + image_num_entries = NUM_COLORS; + image_num_comp = 3; + + + /* Get the id for the palette. */ + pal_id = GRgetlutid(ri_id,0 ); + if(pal_id == FAIL) { + printf("fail to get palette id.\n"); + return FAIL; + } + + /* Write the palette to file. */ + istat = GRwritelut(pal_id, image_num_comp, image_data_type, + 0, image_num_entries,(VOIDP)palette_data); + if(istat == FAIL) { + printf("fail to write palette.\n"); + return FAIL; + } + image_ref = GRidtoref(ri_id); + if(image_ref == FAIL) { + printf("fail to get reference of image.\n"); + return FAIL; + } + + /* Terminate access to the image. */ + istat = GRendaccess(ri_id); + + /* Terminate access to the GR interface. */ + istat = GRend(gr_id); + + + /*** III. setting SDS data and all SDS attributes. ***/ + + sd_id = SDstart(FILEVG,DFACC_WRITE); + + if (sd_id == FAIL){ + printf (" fail to open sd interface. \n"); + return FAIL; + } + + istat = SDsetfillmode(sd_id,SD_NOFILL); + + if (istat == FAIL) { + printf("error setting fill mode\n"); + return FAIL; + } + sds_id = SDcreate(sd_id,"sds",DFNT_INT32,3,dim_sizes); + if(sds_id == FAIL) { + printf("fail to create sds objects.\n"); + return FAIL; + } + + istat = SDsetfillvalue(sds_id,(VOIDP)(&fill_value)); + + if (istat == FAIL){ + printf("error setting fill value\n"); + return FAIL; + } + + /*** 3.1 write data. ***/ + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + + if(istat == FAIL) { + printf(" sds data written failed. \n"); + return FAIL; + } + /*** 3.2 write dataset attribute ***/ + + istat = SDsetattr(sds_id,"sds.attr",DFNT_CHAR8,10,(VOIDP)attr_value); + if(istat == FAIL) { + printf(" sds data attr. setting failed. \n"); + return FAIL; + } + /*** 3.3 write dataset predefined attribute ***/ + + istat = SDsetdatastrs(sds_id,label,unit,format,coordsys); + if(istat == FAIL) { + printf(" sds data predefined attr. setting failed. \n"); + return FAIL; + } + /*** 3.4 set calibration information. ***/ + + istat = SDsetcal(sds_id,cal,cal_err,offset,offset_err,DFNT_INT32); + if(istat == FAIL) { + printf(" sds data calibrating attr. setting failed. \n"); + return FAIL; + } + + /*** 3.5 write down dimension scale dataset. ***/ + + for (i =0; i<TYP_RANK;i++) { + dim_id = SDgetdimid(sds_id,i); + if(dim_id <0) { + printf("sds set dim id failed. \n"); + return FAIL; + } + if (i==0) { + istat = SDsetdimname(dim_id,dim_name0); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat= SDsetdimscale(dim_id,dim_sizes[0],DFNT_INT32,(VOIDP)dimo_sca); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + } + else { + istat = SDsetdimname(dim_id,dim_name1); + if(istat == FAIL) { + printf("sds set dim.name failed. \n"); + return FAIL; + } + istat = SDsetdimscale(dim_id,dim_sizes[1],DFNT_INT32,(VOIDP)dimo_sca); + if(istat == FAIL) { + printf("sds set dim. scale failed. \n"); + return FAIL; + } + } + + istat=SDsetdimstrs(dim_id,dim_label,dim_unit,dim_format); + if(istat == FAIL) { + printf("sds set dim. predefined attr. failed. \n"); + return FAIL; + } + istat = SDsetattr(dim_id,"sdsdim.attr",DFNT_CHAR8,10,(VOIDP)attr_value); + + if(istat == FAIL) { + printf(" sds dim data attr. setting failed. \n"); + return FAIL; + } + SDendaccess(dim_id); + } + + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("fail to transfer id to reference.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupb_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add reference into vgroup.\n"); + return FAIL; + } + + SDendaccess(sds_id); + SDend(sd_id); + + sd_id = SDstart(FILEVG,DFACC_WRITE); + + if (sd_id == FAIL){ + printf (" open file failed\n"); + return FAIL; + } + istat = SDsetfillmode(sd_id,SD_NOFILL); + + if (istat == FAIL){ + printf("error setting fill mode\n"); + return FAIL; + } + sds_id = SDcreate(sd_id,"sds2",DFNT_INT32,3,dim_sizes); + if(sds_id == FAIL) { + printf("fail to create sds id.\n"); + return FAIL; + } + istat = SDsetfillvalue(sds_id,(VOIDP)(&fill_value)); + + if (istat == FAIL){ + printf("error setting fill value\n"); + return FAIL; + } + /*** 3.1 write data. ***/ + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + if(istat == FAIL) { + printf("fail to write sds data.\n"); + return FAIL; + } + + sds_ref = SDidtoref(sds_id); + if(sds_ref == FAIL) { + printf("fail to generate reference number.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupd_id,DFTAG_NDG,sds_ref); + if(istat == FAIL) { + printf("fail to add sds reference into groupd.\n"); + return FAIL; + } + + SDendaccess(sds_id); + SDend(sd_id); + + sd_id = SDstart(FILEVG,DFACC_WRITE); + if (sd_id == FAIL) { + printf (" open file failed\n"); + return FAIL; + } + + istat = SDsetfillmode(sd_id,SD_NOFILL); + + if (istat == FAIL) { + printf("error setting fill mode. \n"); + return FAIL; + } + + sds_id = SDcreate(sd_id,"sds2",DFNT_INT32,3,dim_sizes); + if(sds_id == FAIL) { + printf("error creating sds objects.\n"); + return FAIL; + } + + istat = SDsetfillvalue(sds_id,(VOIDP)(&fill_value)); + + if (istat == FAIL) { + printf("error setting fill value\n"); + return FAIL; + } + + /*** 3.1 write data. ***/ + + istat = SDwritedata(sds_id,start,stride,edges,(VOIDP)array_data); + + if(istat == FAIL) { + printf("error writing sds object.\n"); + return FAIL; + } + + SDendaccess(sds_id); + SDend(sd_id); + + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("error starting gr interface.\n"); + return FAIL; + } + + image_ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + image_dims[0] = X_LENGTH; + image_dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_1", image_ncomp, DFNT_INT16, il, + image_dims); + + if(ri_id == FAIL) { + printf("fail to creat GR interface.\n"); + return FAIL; + } + + /* Fill the stored-data array with values. */ + + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data[j][i][0] = (i + j) + 2; + image_data[j][i][1] = (i + j) + 3; + image_data[j][i][2] =(i+j)+1; + } + } + + /* Define the location, pattern, and size of the data set */ + + for (i = 0; i < 2; i++) { + image_start[i] = 0; + image_edges[i] = image_dims[i]; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, image_start, NULL, image_edges, + (VOIDP)image_data); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + /* Initialize the palette to grayscale. */ + for (i = 0; i < NUM_COLORS; i++) { + palette_data[i * 3] = i; + palette_data[i * 3 + 1] = i; + palette_data[i * 3 + 2] = i; + } + + /* Set palette characteristics. */ + + image_data_type = DFNT_UINT8; + image_num_entries = NUM_COLORS; + image_num_comp = 3; + + + /* Get the id for the palette. */ + pal_id = GRgetlutid(ri_id,0 ); + + if(pal_id == FAIL) { + printf("fail to get palette id.\n"); + return FAIL; + } + + /* Write the palette to file. */ + istat = GRwritelut(pal_id, image_num_comp, image_data_type, + 0, image_num_entries,(VOIDP)palette_data); + if(istat == FAIL) { + printf("fail to write palette data.\n"); + return FAIL; + } + + image_ref = GRidtoref(ri_id); + if(image_ref == FAIL) { + printf("fail to obtain image reference number.\n"); + return FAIL; + } + istat = Vaddtagref(vgroupd_id,DFTAG_RIG,image_ref); + if(istat == FAIL) { + printf("fail to add image into group vgroupd\n"); + return FAIL; + } + + /* Terminate access to the image. */ + istat = GRendaccess(ri_id); + if(istat == FAIL) { + printf("fail to end GR interface.\n"); + return FAIL; + } + + /* Terminate access to the GR interface. */ + istat = GRend(gr_id); + + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("fail to start GR interface.\n"); + return FAIL; + } + + image_ncomp = 3; + il = MFGR_INTERLACE_PIXEL; + image_dims[0] = X_LENGTH; + image_dims[1] = Y_LENGTH; + + /* Create the array. */ + ri_id = GRcreate(gr_id, "Image_2", image_ncomp, DFNT_INT16, il, + image_dims); + if(ri_id == FAIL) { + printf("fail to create GR interface.\n"); + return FAIL; + } + + /* Fill the stored-data array with values. */ + + for (j = 0; j < Y_LENGTH; j++) { + for (i = 0; i < X_LENGTH; i++) { + image_data[j][i][0] = (i + j) + 2; + image_data[j][i][1] = (i + j) + 3; + image_data[j][i][2] =(i+j)+1; + } + } + + /* Define the location, pattern, and size of the data set */ + + for (i = 0; i < 2; i++) { + image_start[i] = 0; + image_edges[i] = image_dims[i]; + } + + /* Write the stored data to the image array. */ + istat = GRwriteimage(ri_id, image_start, NULL, image_edges, + (VOIDP)image_data); + + if(istat == FAIL) { + printf("fail to write image.\n"); + return FAIL; + } + + /* Initialize the palette to grayscale. */ + for (i = 0; i < NUM_COLORS; i++) { + palette_data[i * 3] = i; + palette_data[i * 3 + 1] = i; + palette_data[i * 3 + 2] = i; + } + + /* Set palette characteristics. */ + + image_data_type = DFNT_UINT8; + image_num_entries = NUM_COLORS; + image_num_comp = 3; + + + /* Get the id for the palette. */ + pal_id = GRgetlutid(ri_id,0 ); + if(pal_id == FAIL) { + printf("fail to obtain palette id.\n"); + return FAIL; + } + + /* Write the palette to file. */ + istat = GRwritelut(pal_id, image_num_comp, image_data_type, + 0, image_num_entries,(VOIDP)palette_data); + + if(istat == FAIL) { + printf("fail to write GR image.\n"); + return FAIL; + } + + image_ref = GRidtoref(ri_id); + if(image_ref == FAIL) { + printf("fail to generate image reference number.\n"); + return FAIL; + } + + istat = Vaddtagref(vgroupa_id,DFTAG_RIG,image_ref); + if(istat == FAIL) { + printf("fail to add image into vgroupa\n"); + return FAIL; + } + + /* Terminate access to the image. */ + istat = GRendaccess(ri_id); + + /* Terminate access to the GR interface. */ + istat = GRend(gr_id); + + istat =Vdetach(vgroupb_id); + /* Detach from the vgroup, close the V interface and the file. */ + istat = Vdetach(vgroupa_id); + istat = Vdetach(vgroupc_id); + istat = Vdetach(vgroupd_id); + istat = Vdetach(vgroupe_id); + istat = Vend(file_id); + + istat = Hclose(file_id); + return 0; +} +/* this routine creates annotation for four cases: + +1. file label +2. file description +3. object label(vgroup) +4. object description(vgroup) + +*/ + +int test_anno() { + + int32 file_id, an_id, ann_id, vgroup_id,istat; + uint16 obj_tag, obj_ref; + static char file_label[] = "This is a file label."; + static char file_desc[] = "This is a file description."; + static char data_labelvg[] = "This is a vgroup data label."; + static char data_descvg[] = "This is a vgroup data description."; + + /* Create the HDF file. */ + file_id = Hopen(FILEANNO, DFACC_CREATE, 0); + if(file_id == FAIL) { + printf("fail to open HDF file \n"); + return FAIL; + } + /* Initialize the AN interface and obtain an interface id. */ + an_id = ANstart(file_id); + if(an_id == FAIL) { + printf("fail to start annotation interface.\n"); + return FAIL; + } + + /* Create a file label and obtain an annotation id. */ + ann_id = ANcreatef(an_id, AN_FILE_LABEL); + if(ann_id == FAIL) { + printf("fail to create annotation id.\n"); + return FAIL; + } + + /* Write the file label to the file. */ + istat = ANwriteann(ann_id, file_label, (int32)(strlen(file_label))); + if(istat == FAIL) { + printf("fail to write annotation.\n"); + return FAIL; + } + + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Create a file description. */ + ann_id = ANcreatef(an_id, AN_FILE_DESC); + if(ann_id == FAIL) { + printf("fail to create annotation\n"); + return FAIL; + } + + /* Write the file description to the file. */ + istat = ANwriteann(ann_id, file_desc, (int32)(strlen(file_desc))); + if(istat == FAIL) { + printf("fail to write annotation.\n"); + return FAIL; + } + + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + + /* Create a vgroup. */ + istat = Vstart(file_id); + if(istat == FAIL) { + printf("fail to start v interface.\n"); + return FAIL; + } + + vgroup_id = Vattach(file_id, -1, "w"); + if(vgroup_id == FAIL) { + printf("fail to attach vgroup \n"); + return FAIL; + } + + istat = Vsetname (vgroup_id, "Vgroup w/Annotations"); + if(istat == FAIL) { + printf("fail to set group name\n"); + return FAIL; + } + /* Get reference number of vgroup just created. */ + obj_ref = Vfind (file_id, "Vgroup w/Annotations"); + if(obj_ref == 0) { + printf("fail to set object reference.\n"); + return FAIL; + } + obj_tag = DFTAG_VG; + + /* Create a data label for the Vgroup just created. */ + ann_id = ANcreate(an_id, (uint16)obj_tag, (uint16)obj_ref, AN_DATA_LABEL); + if(ann_id == FAIL) { + printf("fail to create annotation.\n"); + return FAIL; + } + /* Write the data label to the file. */ + istat = ANwriteann(ann_id, data_labelvg, (int)(strlen(data_labelvg))); + if(istat == FAIL){ + printf("fail to write annotation.\n"); + return FAIL; + } + istat = ANendaccess(ann_id); + + obj_tag = DFTAG_VG; + + /* Create a data description for the Vgroup just created.*/ + ann_id = ANcreate(an_id, (uint16)obj_tag, (uint16)obj_ref, AN_DATA_DESC); + if(ann_id == FAIL) { + printf("fail to create annotation.\n"); + return FAIL; + } + + /* Write the data description to the file. */ + istat = ANwriteann(ann_id, data_descvg, (int)(strlen(data_descvg))); + if(istat == FAIL) { + printf("fail to write annotation.\n"); + return FAIL; + } + /* Terminate access to the annotation. */ + istat = ANendaccess(ann_id); + istat = Vdetach(vgroup_id); + istat = Vend(file_id); + /* Close the file. */ + + /* Terminate access to the AN interface. */ + istat = ANend(an_id); + istat = Hclose(file_id); + return 0; +} + + + + + + + diff --git a/tools/h4toh5/h4toh5util.c b/tools/h4toh5/h4toh5util.c new file mode 100644 index 0000000..879e8a9 --- /dev/null +++ b/tools/h4toh5/h4toh5util.c @@ -0,0 +1,1633 @@ +/*------------------------------------------------------------------------- + * + * 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 all routines that are useful for other files. + +Author: Kent Yang(ymuqun@ncsa.uiuc.edu) + + +*****************************************************************************/ + + +#include "h4toh5util.h" + + +/* Function h4toh5_ZeroMemory + Purpose: Zero out memory + return: None + In: size_t n(DWORD in windows) + void* s(PVOID in windows) +*/ +void h4toh5_ZeroMemory(void*s,size_t n) { +#ifdef WIN32 + ZeroMemory(s,n); +#else + bzero(s,n); +#endif +} + +/*------------------------------------------------------------------------- + * Function: h5string_to_int + * + * Purpose: This function will convert H5T_STRING into integer. + This is a correction routine when the user define the + numerical datatype int8 as DFNT_CHAR8 and DFNT_UCHAR8 + + * Errors: will return error message to the interface + * Return: FAIL if failed, SUCCEED if success + * + * In : h4type: HDF4 datatype + h4memsize: the real memory size of h4type + + * Out: h5memtype: pointer of which value should be h5memtype(the real + data type stored at the memory) + h5type: pointer of which value should be h5type(the hdf5 + type stored at the disk). + * + *------------------------------------------------------------------------- + */ + +int h5string_to_int(const int32 h4type, hid_t* h5memtype, + const size_t h4memsize,hid_t* h5type) { + + switch(h4type) { + + case DFNT_CHAR8: + + *h5type = H5T_STD_I8BE; + if (h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_SCHAR; + else if(h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_UCHAR8: + + *h5type = H5T_STD_U8BE; + if (h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + } + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: h4type_to_h5type + * + * Purpose: this function will convert HDF4 datatype into HDF5 datatype + The converter includes file to file datatype and datasize + conversion, file to memory datatype and datasize conversion. + Check the mapping document for details. + + * Errors: will return error message to the interface. + * Return: false, FAIL. otherwise,SUCCEED. + * + * In : h4type: HDF4 datatype. + * Out: h4size: the file(disk) size of h4type. + h4memsize: the real memory size of h4type. + * h5memtype: pointer of which value should be h5memtype(the real + type stored at the memory). + h5type: pointer of which value should be h5type(the hdf5 + type that is stored at the disk). + * + * + *------------------------------------------------------------------------- + */ +int h4type_to_h5type(const int32 h4type, hid_t* h5memtype, + size_t* h4memsize,size_t* h4size, hid_t *h5type) +{ + + switch (h4type) { + + case DFNT_CHAR8: + + *h4size = 1; + *h4memsize = sizeof(int8); + /* assume DFNT_CHAR8 C type character. */ + *h5memtype = H5T_STRING; + *h5type = H5T_STRING; + break; + + case DFNT_UCHAR8: + + *h4size = 1; + *h4memsize = sizeof(int8); + *h5memtype = H5T_STRING; + *h5type = H5T_STRING; + break; + + case DFNT_INT8: + + *h4size = 1; + *h5type = H5T_STD_I8BE; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_SCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_UINT8: + + *h4size =1; + *h5type = H5T_STD_U8BE; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_NINT8: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 1; + *h5type = H5T_NATIVE_SCHAR; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_SCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_NUINT8: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 1; + *h5type = H5T_NATIVE_UCHAR; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_LINT8: + *h4size = 1; + *h5type = H5T_STD_I8LE; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_LUINT8: + *h4size = 1; + *h5type = H5T_STD_U8LE; + *h4memsize = sizeof(int8); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_INT16: + *h4size = 2; + *h5type = H5T_STD_I16BE; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_CHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_UINT16: + *h4size = 2; + *h5type = H5T_STD_U16BE; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_NINT16: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 2; + *h5type = H5T_NATIVE_SHORT; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_CHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_NUINT16: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 2; + *h5type = H5T_NATIVE_USHORT; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_LINT16: + *h4size = 2; + *h5type = H5T_STD_I16LE; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_LUINT16: + *h4size = 2; + *h5type = H5T_STD_U16LE; + *h4memsize = sizeof(int16); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_INT32: + *h4size = 4; + *h5type = H5T_STD_I32BE; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_CHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_UINT32: + *h4size = 4; + *h5type = H5T_STD_U32BE; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_NINT32: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 4; + *h5type = H5T_NATIVE_INT; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_CHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_NUINT32: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting results may not be correct.\n"); + *h4size =4; + *h5type = H5T_NATIVE_UINT; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_LINT32: + *h4size =4; + *h5type = H5T_STD_I32LE; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_CHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_SHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_INT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_LONG; + else return FAIL; + break; + + case DFNT_LUINT32: + *h4size =4; + *h5type = H5T_STD_U32LE; + *h4memsize = sizeof(int32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_CHAR)) + *h5memtype = H5T_NATIVE_UCHAR; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_SHORT)) + *h5memtype = H5T_NATIVE_USHORT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_INT)) + *h5memtype = H5T_NATIVE_UINT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_LONG)) + *h5memtype = H5T_NATIVE_ULONG; + else return FAIL; + break; + + case DFNT_FLOAT32: + *h4size =4; + *h5type = H5T_IEEE_F32BE; + *h4memsize = sizeof(float32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + case DFNT_FLOAT64: + *h4size = 8; + *h5type = H5T_IEEE_F64BE; + *h4memsize = sizeof(float64); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + case DFNT_NFLOAT32: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting results may not be correct.\n"); + *h4size = 4; + *h5type = H5T_NATIVE_FLOAT; + *h4memsize = sizeof(float32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + case DFNT_NFLOAT64: + printf("warning, Native HDF datatype is encountered"); + printf(" the converting result may not be correct.\n"); + *h4size = 8; + *h5type = H5T_NATIVE_DOUBLE; + *h4memsize = sizeof(float64); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + case DFNT_LFLOAT32: + *h4size = 4; + *h5type = H5T_IEEE_F32LE; + *h4memsize = sizeof(float32); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + case DFNT_LFLOAT64: + *h4size = 8; + *h5type = H5T_IEEE_F64LE; + *h4memsize = sizeof(float64); + if(*h4memsize == H5Tget_size(H5T_NATIVE_FLOAT)) + *h5memtype = H5T_NATIVE_FLOAT; + else if(*h4memsize == H5Tget_size(H5T_NATIVE_DOUBLE)) + *h5memtype = H5T_NATIVE_DOUBLE; + else return FAIL; + break; + + default: + return FAIL; + } + return SUCCEED; +} +/*------------------------------------------------------------------------- + * Function: conv_int_str + * + * Purpose: this function will convert numerical number into the + string format for a reference(<=65536). + * Return: SUCCEED if success, FAIL if failed. + * + * In : num: an unsigned digital number that is not greater than 65536. + + * Out: str_num: character string format of the number. + + * + * + *------------------------------------------------------------------------- + */ + +int conv_int_str(uint16 num, char* str_num) { + + /* the maximum reference number is 65536. */ + + + if(str_num == NULL) { + printf(" memory for str_num should be allocated.\n"); + return FAIL; + } + + /* Adding this line will cause problems, investigating this later. +h4toh5_ZeroMemory(str_num,strlen(str_num)+1);*/ + + sprintf(str_num,"%d",num); + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: lookup + * + * Purpose: this function will use objref as a key to check whether + * the current object is touched. + + * Return: 1, the object is found. 0,the object is not found. + -1, the table doesn't exist. + * + * In : objref: reference number of the current object. + SIZE: the hashtable SIZE. + hashtab: pointer to the hash table. + + *------------------------------------------------------------------------- + */ + +int lookup(int objref,int SIZE,struct table*hashtab) { + + struct table *np; + if(hashtab == NULL) { + printf("the table doesn't exist. \n"); + return -1; + } + np = hashtab+objref%SIZE; + + for (np = hashtab+objref%SIZE; np!=NULL;np=np->next){ + 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 <num_vgattr;i++) { + + if (Vattrinfo(h4vg,i,vgattr_name,&vg_atype, + &count_vgattr,&attr_size)== FAIL){ + printf("unable to obtain attribute information. \n"); + return FAIL; + } + + /* convert attribute datatype into the corresponding hdf5 datatype */ + + if(h4type_to_h5type(vg_atype,&sh5_amemtype,&sh4_amemsize, + &sh4_size,&sh5_atype)==FAIL){ + printf("unable to do data type converting.\n"); + return FAIL; + } + + vg_adata = malloc(sh4_amemsize*count_vgattr); + + if(vg_adata == NULL) { + printf("error in allocating vgroup attribute data. \n"); + return FAIL; + } + + if(Vgetattr(h4vg,i,(VOIDP)vg_adata)==FAIL){ + printf("unable to get attribute.\n"); + free(vg_adata); + return FAIL; + } + + /* if the attribute doesn't have a name, a default name is set. */ + if(vgattr_name[0] == '\0') + strcpy(vgattr_name,trans_obj_name(DFTAG_VG,i)); + + /* now do attribute-transferring. + 1. deal with string data type + 2. set attribute space + 3. get attribute name, set property list. */ + + if (sh5_atype == H5T_STRING ) { + + sh5a_sid = H5Screate(H5S_SCALAR); + + if (sh5a_sid < 0) { + printf("failed to create attribute space "); + printf("for HDF4_OBJECT_TYPE SDS. \n"); + free(vg_adata); + return FAIL; + } + + if ((sh5str_type = mkstr(count_vgattr*sh4_size,H5T_STR_SPACEPAD))<0) { + fprintf(stderr,"error in making string for VGROUP ATTR. \n"); + free(vg_adata); + return FAIL; + } + + + if ((sh5str_memtype = mkstr(count_vgattr*sh4_amemsize, + H5T_STR_SPACEPAD))<0){ + fprintf(stderr,"error in making memory string for VGROUP ATTR. \n"); + free(vg_adata); + return FAIL; + } + + sh5a_id = H5Acreate(h5g,vgattr_name,sh5str_type,sh5a_sid,H5P_DEFAULT); + + if (sh5a_id <0) { + printf("failed to obtain attribute id"); + printf(" for HDF4_OBJECT_TYPE VGROUP. \n"); + free(vg_adata); + return FAIL; + } + sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)vg_adata); + + if (sret <0) { + fprintf(stderr,"failed to obtain attribute.\n "); + free(vg_adata); + return FAIL; + } + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + + else { + + if (count_vgattr == 1) { + sh5a_sid = H5Screate(H5S_SCALAR); + if (sh5a_sid < 0) { + fprintf(stderr,"failed to create space id. \n"); + free(vg_adata); + return FAIL; + } + } + + else { + + sh5dims[0] = count_vgattr; + sh5a_sid = H5Screate_simple(1,sh5dims,NULL); + if (sh5a_sid < 0) { + fprintf(stderr,"failed to create vgroup attribute space. \n"); + free(vg_adata); + return FAIL; + } + } + + sh5a_id = H5Acreate(h5g,vgattr_name,sh5_atype,sh5a_sid,H5P_DEFAULT); + + if(sh5a_id <0) { + fprintf(stderr,"failed to obtain attribute id. \n"); + free(vg_adata); + H5Sclose(sh5a_sid); + return FAIL; + } + sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)vg_adata); + + if(sret < 0) { + fprintf(stderr,"failed to obtain attribute.\n "); + free(vg_adata); + H5Sclose(sh5a_sid); + H5Aclose(sh5a_id); + return FAIL; + } + + sret = H5Sclose(sh5a_sid); + sret = H5Aclose(sh5a_id); + } + free(vg_adata); + } + + /*** check this line later. ***/ + strcpy(obtype,VGROUPLABEL); + vgroup_class[0] = '\0'; + + /* ignore CDF0.0 and RIG0.0 vgroups. */ + if(Vgetclass(h4vg,vgroup_class) == SUCCEED){ + if(vgroup_class[0] != '\0') { + if(!strcmp(vgroup_class,_HDF_CDF)|| + !strcmp(vgroup_class,GR_NAME)) + return SUCCEED; + } + } + + /* transfer predefined attributes. */ + if(h4_transpredattrs(h5g,HDF4_OBJECT_TYPE,obtype)==FAIL){ + printf("error in data attribute transferring.\n"); + return FAIL; + } + + if(Vgetname(h4vg,vgroup_name) == SUCCEED){ + if(vgroup_name[0] != '\0') { + if(h4_transpredattrs(h5g,HDF4_OBJECT_NAME,vgroup_name)==FAIL){ + printf("error in data attribute transferring.\n"); + return FAIL; + } + } + } + + if(vgroup_class[0] !='\0') { + if(h4_transpredattrs(h5g,HDF4_VGROUP_CLASS,vgroup_class)==FAIL){ + printf("error in data attribute transferring.\n"); + return FAIL; + } + } + + vgroup_cref = VQueryref(h4vg); + if(vgroup_cref == FAIL) { + printf("failed to obtain group reference number.\n"); + return FAIL; + } + + if(h4_transnumattr(h5g,HDF4_REF_NUM,vgroup_cref)==FAIL){ + printf("error in data attribute transferring.\n"); + return FAIL; + } + + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: get_obj_aboname + * + * Purpose: get absolute path name of hdf5 object + In this function, we will deal with name clashing. + If we find an object name(by using lookup_name routine) + that has already been used, + we will remake name for this object. We will follow + object type(vgroup,sds,image,palette, vdata) plus reference + number to make it unique. + * + * Return: NULL if failed, object name if successful. + * + * In : + obj_name: relative object name + ref_str: reference number in character format + path_name: absolute path + objstr: object type in character format + + *------------------------------------------------------------------------- + */ + +char* get_obj_aboname(char* obj_name,char* refstr,char* path_name, + const char*objstr ) { + + char *abo_objname; + int check_name; + char check_char; + + + /* sometimes although the object name is not NULL, but it is empty. + We will use make_objname_no under this situation. */ + if(obj_name != NULL) check_char = *obj_name; + + /* obtain the absolute name of the object. */ + if (obj_name == NULL || check_char == '\0') + abo_objname = make_objname_no(refstr,path_name,objstr); + else + abo_objname = make_objname_yes(obj_name,path_name); + + /* look up the name and see whether there is name clashing here. + if yes, remake the object name.*/ + check_name = lookup_name(abo_objname,num_objects,name_hashtab); + + if(check_name == 1) { + /* name_clashing is found. */ + if(objstr != NULL && refstr != NULL){ + free(abo_objname); + + if(path_name != NULL) { + abo_objname= malloc(strlen(path_name)+strlen(objstr)+ + strlen(refstr)+3); + if(abo_objname == NULL) { + printf("error in allocating memory. \n"); + return NULL; + } + h4toh5_ZeroMemory(abo_objname,strlen(path_name)+strlen(objstr)+ + strlen(refstr)+3); + strcpy(abo_objname,path_name); + strcat(abo_objname,"/"); + strcat(abo_objname,objstr); + strcat(abo_objname,"_"); + strcat(abo_objname,refstr); + } + + else { + abo_objname= malloc(strlen(objstr)+strlen(refstr)+3); + if(abo_objname == NULL) { + printf("error in allocating memory. \n"); + return NULL; + } + h4toh5_ZeroMemory(abo_objname,strlen(objstr)+strlen(refstr)+3); + strcat(abo_objname,"/"); + strcat(abo_objname,objstr); + strcat(abo_objname,"_"); + strcat(abo_objname,refstr); + } + } + } + + return abo_objname; +} + +/*------------------------------------------------------------------------- + * Function: make_objname_no + * + * Purpose: get absolute path name of hdf5 object when object name is + not defined. + We will use path name and + object type(vgroup,sds,image,palette, vdata) plus reference + number to make it unique. + * + * Return: NULL if failed, object name if successful. + * + * In : + ref_str: reference number in character format + path_name: absolute path + objstr: object type in character format + + *------------------------------------------------------------------------- + */ + +char* make_objname_no(char* refstr,char* path_name,const char*objstr) { + + char *new_objname; + + if(objstr == NULL || refstr == NULL) { + printf("error, object type and ref. number should be defined.\n"); + return NULL; + } + + if (path_name == NULL) {/* under root group. */ + + new_objname= malloc(strlen(objstr)+strlen(refstr)+3); + if(new_objname == NULL) { + printf("error in allocating memory for object name. \n"); + return NULL; + } + h4toh5_ZeroMemory(new_objname,strlen(objstr)+strlen(refstr)+3); + strcpy(new_objname,"/"); + strcat(new_objname,objstr); + strcat(new_objname,"_"); + strcat(new_objname,refstr); + } + + else { + + new_objname= malloc(strlen(path_name)+strlen(objstr)+strlen(refstr)+3); + if(new_objname == NULL) { + printf("error in allocating memory. \n"); + return NULL; + } + h4toh5_ZeroMemory(new_objname,strlen(path_name)+strlen(objstr)+strlen(refstr)+3); + strcpy(new_objname,path_name); + strcat(new_objname,"/"); + strcat(new_objname,objstr); + strcat(new_objname,"_"); + strcat(new_objname,refstr); + } + + return new_objname; +} + +/*------------------------------------------------------------------------- + * Function: make_objname_yes + * + * Purpose: get absolute path name of hdf5 object when object name is + defined. + + * + * Return: NULL if failed, object name if successful. + * + * In : obj_name: object name + path_name: absolute path + + *------------------------------------------------------------------------- + */ + +char* make_objname_yes(char* obj_name,char* path_name){ + + char*new_objname; + + if(path_name == NULL) { + new_objname = malloc(strlen(obj_name)+2); + if(new_objname == NULL) { + printf("error in allocating memory. \n"); + return NULL; + } + h4toh5_ZeroMemory(new_objname,strlen(obj_name)+2); + strcpy(new_objname,"/"); + strcat(new_objname,obj_name); + } + else { + new_objname = malloc(strlen(path_name)+strlen(obj_name)+2); + if(new_objname == NULL) { + printf("error in allocating memory. \n"); + return NULL; + } + h4toh5_ZeroMemory(new_objname,strlen(path_name)+strlen(obj_name)+2); + strcpy(new_objname,path_name); + strcat(new_objname,"/"); + strcat(new_objname,obj_name); + } + return new_objname; +} + +/*------------------------------------------------------------------------- + * Function: trans_obj_name + * + * Purpose: obtain hdf4 attribute name from hdf4 object type + plus ATTR plus reference number. + * + * Return: object name; + * + * In : + obj_tag: hdf4 tag + index : hdf5 group id + + *------------------------------------------------------------------------- + */ +char* trans_obj_name(int32 obj_tag,int32 index) { + + char* obj_name; + char indstr[5]; + + /* the reason why we allocate memory with strlen(HDF4_PALETTE) is + HDF4_PALETTE is the longest string among HDF4_??? */ + obj_name = malloc(strlen(HDF4_PALETTE)+strlen(ATTR)+8); + if(obj_name == NULL) { + printf("cannot allocate memory for object name. \n"); + return NULL; + } + + h4toh5_ZeroMemory(obj_name,strlen(HDF4_PALETTE)+strlen(ATTR)+8); + + if(conv_int_str(index,indstr)== FAIL) { + printf("indstr is not allocated. \n"); + return NULL; + } + + switch(obj_tag) { + + case DFTAG_SD: + case DFTAG_NDG: + case DFTAG_SDG: + strcpy(obj_name,HDF4_SDS); + break; + + case DFTAG_RIG: + case DFTAG_RI: + case DFTAG_RI8: + strcpy(obj_name,HDF4_IMAGE); + break; + + case DFTAG_VG: + strcpy(obj_name,HDF4_VGROUP); + break; + + case DFTAG_VH: + case DFTAG_VS: + strcpy(obj_name,HDF4_VDATA); + break; + + case DFTAG_LUT: + strcpy(obj_name,HDF4_PALETTE); + break; + + default: + printf("error, object tag is transferred out of limits. \n"); + free(obj_name); + return NULL; + } + + strcat(obj_name,"_"); + strcat(obj_name,ATTR); + strcat(obj_name,"_"); + strcat(obj_name,indstr); + + return obj_name; +} +/*------------------------------------------------------------------------- + * Function: freehashmemory + * + * Purpose: free memories allocated for hash tables. + + * + * Return: NULL + * + * In : + + + *------------------------------------------------------------------------- + */ + +void freehashmemory(void){ + + if(estnum_vg > 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 <assert.h> + +/*------------------------------------------------------------------------- + * 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<nfields;i++) { + + /* obtain field type. */ + fieldtype = VFfieldtype(vdata_id,i); + if(fieldtype == FAIL){ + printf("error in obtaining field type. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + return FAIL; + } + + /* obtain field order.*/ + fieldorder = VFfieldorder(vdata_id,i); + /* printf("fieldorder %d\n",fieldorder);*/ + if(fieldorder == FAIL){ + printf("error in obtaining field order. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + return FAIL; + } + + /* datatype conversion from hdf4 to hdf5. + the corresponding memory data type is also converted.*/ + if(h4type_to_h5type(fieldtype,&h5memtype[i],&h4memsize[i], + &h4size[i],&h5type[i])== FAIL){ + printf("error in doing datatype conversion at vdata routine. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + return FAIL; + } + + vdatamem_size +=fieldorder*h4memsize[i]; + vdata_size +=fieldorder*h4size[i]; + + } + + vd_data = malloc((size_t)(vdatamem_size*n_records)); + + istat = VSsetfields(vdata_id,field_name_list); + + if(istat == FAIL) { + printf("error setting fields of vdata.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + istat = VSread(vdata_id,(uint8*)vd_data,n_records,FULL_INTERLACE); + + if(istat == FAIL) { + printf("error in obtaining vdata. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + for (i=0;i<nfields;i++) { + /* obtain field order.*/ + fieldorder = VFfieldorder(vdata_id,i); + + if(fieldorder == FAIL){ + printf("error in obtaining field order. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + return FAIL; + } + } + /* create hdf5 compound datatype for both memory and file.*/ + + h5_ctype = H5Tcreate(H5T_COMPOUND, (size_t)vdata_size); + h5_cmemtype = H5Tcreate(H5T_COMPOUND,(size_t)vdatamem_size); + + if(gen_h5comptype(vdata_id,nfields,h4size,h4memsize,h5type,h5memtype, + h5_ctype,h5_cmemtype)==FAIL){ + printf("error in generating h5 compound data type.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + h5_vddims[0] = n_records; + h5d_sid = H5Screate_simple(1,h5_vddims,NULL); + + if(h5d_sid <0){ + printf("error in obtaining space id.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + /* choose a number that is not returned from the func.*/ + check_vdname = -3; + + /* obtain hdf5 vdata name. */ + h5cvdata_name = get_name(vdata_ref,estnum_vd,vd_hashtab,&check_vdname); + + if (h5cvdata_name == NULL && check_vdname == 0 ) { + printf("error,cannot find vdata \n"); + return FAIL; + } + + if (h5cvdata_name == NULL && check_vdname == -1) { + printf("error,group name is not defined.\n"); + return FAIL; + } + + if (h5cvdata_name == NULL && check_vdname == -2 ) { + printf("cannot allocate memory for vdata.\n"); + return FAIL; + } + + h5dset = H5Dcreate(group_id,h5cvdata_name,h5_ctype,h5d_sid,H5P_DEFAULT); + if(h5dset <0) { + printf("error in obtaining dataset.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + free(h5cvdata_name); + return FAIL; + } + free(h5cvdata_name); + + if(H5Dwrite(h5dset,h5_cmemtype,H5S_ALL,H5S_ALL,H5P_DEFAULT,vd_data)<0){ + printf("error in writing dataset converted from vdata.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + /* handle vdata attributes and vdata field attributes. */ + + num_vd_attrs = VSfnattrs(vdata_id,_HDF_VDATA); + + if (num_vd_attrs == FAIL) { + printf("error in obtaining attributes of vdata.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + /* when field_index = -1, only transfer vdata attribute.*/ + + field_index = -1; + if(vdata_transattrs(vdata_id,h5dset,num_vd_attrs,field_index,NULL)==FAIL){ + printf("error in translating vdata attibutes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + for (i =0;i< nfields;i++) { + + if(VFfieldname(vdata_id,i)== NULL) { + printf("error in obtaining field name. \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + strcpy(fieldname,VFfieldname(vdata_id,i)); + num_vd_field_attrs = VSfnattrs(vdata_id,i); + if(num_vd_field_attrs == FAIL){ + printf("error in number of vd field attribute \n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + if(vdata_transattrs(vdata_id,h5dset,num_vd_field_attrs,i,fieldname) + ==FAIL){ + printf("error in transfering vdata attributes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + } + /* converting annotations of vdata into corresponding hdf5 attribute.*/ + if( Annoobj_h4_to_h5(file_id,vdata_ref,vdata_tag,h5dset)== FAIL){ + printf("fail to convert HDF4 VDATA annotation into hdf5 attributes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + /* converting predefined attributes. */ + strcpy(vdlabel,VDATALABEL); + if(h4_transpredattrs(h5dset,HDF4_OBJECT_TYPE,vdlabel)==FAIL){ + printf("error in transfering vdata attributes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + if(vdata_name[0] != '\0') { + if(h4_transpredattrs(h5dset,HDF4_OBJECT_NAME,vdata_name)==FAIL){ + printf("error in transfering vdata attributes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + } + + if(h4_transnumattr(h5dset,HDF4_REF_NUM,vdata_ref)==FAIL){ + printf("error in transfering vdata attributes.\n"); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return FAIL; + } + + H5Sclose(h5d_sid); + H5Dclose(h5dset); + VSdetach(vdata_id); + free(h5memtype); + free(h5type); + free(h4memsize); + free(h4size); + free(vd_data); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: vdata_transattrs + * + * Purpose: translate Vdata attributes into attributes of the + corresponding hdf5 dataset + * + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + vdata_id: vdata identifier + h5dset: hdf5 dataset + snum_vdattrs: number of vd attributes + field_index: index of vdata fields + attr_name: vdata(or vdata field) attribute name + Out: + Modifications: + + *------------------------------------------------------------------------- + */ + +int vdata_transattrs(int32 vdata_id,hid_t h5dset,int snum_vdattrs, + int field_index,char* attr_name){ + + char svdattr_name[2*MAX_NC_NAME]; + char* svdrepattr_name; + char refstr[MAXREF_LENGTH]; + + int32 count_svdadata; + int32 svd_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[1]; + void* svd_adata; + herr_t sret; + int i; + + /* zeroing out memory for svdattr_name and refstr */ + h4toh5_ZeroMemory(svdattr_name,2*MAX_NC_NAME); + h4toh5_ZeroMemory(refstr,MAXREF_LENGTH); + + /* separate vdata attribute from vdata field attributes. */ + + if (field_index < -1) { + printf("error: check_field should be either -1(vdata) or "); + printf(">=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<num_gobjects;i++) { + + if(Vgettagref(vgroup_id,i,&obj_tag,&obj_ref)==FAIL) { + printf("failed to get object tag and ref of the current"); + printf(" object in this vgroup.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("failed to convert object reference number "); + printf("into string format at vgroup_h4_to_h5 routine.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + + if (Visvg(vgroup_id,obj_ref)) { + + if(convert_vgroup(file_id,sd_id,obj_ref,h5pgroup_name,h5_pgroup, + h5_dimgroup,h5_palgroup)== FAIL) { + printf("convert_vgroup routine failed,"); + printf("cannot convert vgroup into hdf5 group successfully.\n"); + free(h5pgroup_name); + H5Gclose(h5_pgroup); + return FAIL; + } + + } + /* the object is independent vdata. */ + else if(Visvs(vgroup_id,obj_ref)) { + if(convert_vdata(file_id,obj_ref,h5pgroup_name,h5_pgroup)==FAIL){ + printf("fail to convert vdata into hdf5 dataset.\n"); + free(h5pgroup_name); + H5Gclose(h5_pgroup); + return FAIL; + } + } + else if(obj_tag == DFTAG_NDG || obj_tag == DFTAG_SDG) { + if(convert_sds(file_id,sd_id,obj_ref,h5pgroup_name,h5_pgroup, + h5_dimgroup)==FAIL){ + printf("fail to convert sds into hdf5 dataset.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + } + else if(obj_tag == DFTAG_RIG) { + if(convert_image(file_id,obj_ref,h5pgroup_name, + h5_pgroup,h5_palgroup)==FAIL){ + printf("fail to convert image into hdf5 dataset.\n"); + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return FAIL; + } + } + } + + H5Gclose(h5_pgroup); + free(h5pgroup_name); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: convert_vgroup + * + * Purpose: subroutine interface for better modularity of vgroup_h4_to_h5 + * In this routine, 1) h5 vgroup name is obtained; + 2) vgroup_h4_to_h5 is called again for + unvisited vgroups + 3) HardLink is created for visited vgroups + + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf4 file identifier + sd_id: sd interface id + obj_ref: object reference number + h5pgroup_name: h5 group name + h5_pgroup: hdf5 group id + h5_dimgroup: hdf5 dimensional scale group id + h5_palgroup: hdf5 palette group id + + *------------------------------------------------------------------------- + */ + +int convert_vgroup(int32 file_id,int32 sd_id, int32 obj_ref, + char* h5pgroup_name,hid_t h5_pgroup,hid_t h5_dimgroup, + hid_t h5_palgroup) { + + int32 vgroup_cid; + int32 istat; + int check_vgname; + char refstr[MAXREF_LENGTH]; + char cvgroup_name[VGNAMELENMAX]; + char* cor_cvgroupname; + char* h5cgroup_name; + char* h5lgroup_name; + int check_vgroup; + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("converting integer into string format.\n"); + return FAIL; + } + + vgroup_cid = Vattach(file_id,obj_ref,"r"); + if(vgroup_cid == FAIL) { + printf("error in getting vgroup id.\n"); + return FAIL; + } + + /* recursively obtain information from the group*/ + /* check whether it is looked up, if yes, create a hard link.*/ + + istat = Vgetname(vgroup_cid,cvgroup_name); + if(istat == FAIL) { + printf("failed to get the name of vgroup.\n"); + Vdetach(vgroup_cid); + return FAIL; + } + + /* look up vg hashtable and see whether this object is touched.*/ + check_vgroup = lookup(obj_ref,estnum_vg,vg_hashtab); + + /* if this vgroup has not been touched, convert it into hdf5 group. + else create a hard link to the existing group.*/ + + cor_cvgroupname = correct_name(cvgroup_name); + if(cor_cvgroupname == NULL) { + printf("error in generating corrected vgroup name. \n"); + Vdetach(vgroup_cid); + return FAIL; + } + if(check_vgroup == 0) { + + /* checking whether vgroup name contains ORI_SLASH, changing into CHA_SLASH.*/ + + h5cgroup_name = get_obj_aboname(cor_cvgroupname,refstr,h5pgroup_name, + HDF4_VGROUP); + if(h5cgroup_name == NULL) { + printf("error in getting the group name.\n"); + Vdetach(vgroup_cid); + free(cor_cvgroupname); + return FAIL; + } + + free(cor_cvgroupname); + if(set_name(obj_ref,estnum_vg,vg_hashtab,h5cgroup_name)== FAIL) { + printf("error in setting group name.\n"); + Vdetach(vgroup_cid); + free(h5cgroup_name); + return FAIL; + } + if(Vgroup_h4_to_h5(file_id,vgroup_cid,sd_id,h5_pgroup, + h5_dimgroup,h5_palgroup)== FAIL) { + printf("error in transferring vgroup into hdf5 group.\n"); + Vdetach(vgroup_cid); + free(h5cgroup_name); + return FAIL; + } + free(h5cgroup_name); + + } + + else { + + h5cgroup_name = get_name(obj_ref,estnum_vg,vg_hashtab,&check_vgname); + if(h5cgroup_name == NULL && check_vgname ==0 ) { + printf("error,cannot find group\n"); + Vdetach(vgroup_cid); + return FAIL; + } + + if(h5cgroup_name == NULL && check_vgname == -1 ) { + printf("error,group name is not defined.\n"); + Vdetach(vgroup_cid); + return FAIL; + } + + /* create HL */ + + + h5lgroup_name = get_obj_aboname(cor_cvgroupname,refstr,h5pgroup_name, + HDF4_VGROUP); + if(h5lgroup_name == NULL) { + printf("failed to obtain group name.\n"); + Vdetach(vgroup_cid); + free(h5cgroup_name); + free(cor_cvgroupname); + return FAIL; + } + free(cor_cvgroupname); + if(H5Glink(h5_pgroup,H5G_LINK_HARD,h5cgroup_name,h5lgroup_name)<0) { + printf("cannot make hard link for two groups.\n"); + Vdetach(vgroup_cid); + free(h5cgroup_name); + free(h5lgroup_name); + return FAIL; + } + free(h5cgroup_name); + free(h5lgroup_name); + } + + Vdetach(vgroup_cid); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: convert_vdata + * + * Purpose: subroutine interface for better modularity of vgroup_h4_to_h5 + * In this routine, 1) h5 vdata name is obtained; + 2) vdata_h4_to_h5 is called for unvisited + vdatas + 3) HardLink is created for visited vdatas + + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf4 file identifier + obj_ref: object reference number + h5pgroup_name: h5 group name + h5_pgroup: hdf5 group id + + *------------------------------------------------------------------------- + */ + +int convert_vdata(int32 file_id,int32 obj_ref,char * h5pgroup_name, + hid_t h5_pgroup) { + + int32 vdata_id; + int check_vdata; + int check_vdname; + int32 istat; + char refstr[MAXREF_LENGTH]; + char cvdata_name[VGNAMELENMAX]; + char* cor_cvdataname; + char* h5cvdata_name; + char* h5lvdata_name; + + vdata_id = VSattach(file_id,obj_ref,"r"); + if(vdata_id == FAIL) { + printf("error in attaching vdata. \n"); + return FAIL; + } + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("converting integer into string format.\n"); + VSdetach(vdata_id); + return FAIL; + } + + istat = VSisattr(vdata_id); + if (istat == FAIL) { + printf("error in checking vdata attribute. \n"); + VSdetach(vdata_id); + return FAIL; + } + + if(istat); /*ignore, dependent vdata(attributes, etc.)can be retrieved later.*/ + + else { /* independent vdata, read in */ + + check_vdata = lookup(obj_ref,estnum_vd,vd_hashtab); + + if(check_vdata < 0) { + printf("failed to look up the object.\n"); + VSdetach(vdata_id); + return FAIL; + } + + if(VSQueryname(vdata_id,cvdata_name)==FAIL) { + printf("error in querying name. \n"); + VSdetach(vdata_id); + return FAIL; + } + + cor_cvdataname = correct_name(cvdata_name); + if(cor_cvdataname == NULL) { + printf("error in generating corrected vdata name. \n"); + VSdetach(vdata_id); + return FAIL; + } + if(check_vdata ==0) { + h5cvdata_name = get_obj_aboname(cor_cvdataname,refstr,h5pgroup_name, + HDF4_VDATA); + if(h5cvdata_name == NULL) { + printf("cannot obtain the converted hdf5 dataset name from vdata.\n"); + VSdetach(vdata_id); + free(cor_cvdataname); + return FAIL; + } + free(cor_cvdataname); + if(set_name(obj_ref,estnum_vd,vd_hashtab,h5cvdata_name)== FAIL){ + printf("failed to obtain vdata name.\n"); + VSdetach(vdata_id); + free(h5cvdata_name); + return FAIL; + } + + if(Vdata_h4_to_h5(file_id,vdata_id,h5_pgroup)==FAIL){ + printf("failed to transfer vdata into hdf5 dataset.\n"); + VSdetach(vdata_id); + free(h5cvdata_name); + return FAIL; + } + free(h5cvdata_name); + } + + else { + + h5cvdata_name = get_name(obj_ref,estnum_vd,vd_hashtab, + &check_vdname); + + if(h5cvdata_name == NULL && check_vdname ==0 ){ + printf("error,cannot find vdata\n"); + VSdetach(vdata_id); + return FAIL; + } + if(h5cvdata_name == NULL && check_vdname ==-1 ){ + printf("error,vdata name is not defined.\n"); + VSdetach(vdata_id); + return FAIL; + } + /*create HL, + for the time being, we will use absolute path. */ + + h5lvdata_name = get_obj_aboname(cor_cvdataname,refstr,h5pgroup_name, + HDF4_VDATA); + if(h5lvdata_name == NULL) { + printf("error in obtaining vdata name.\n"); + VSdetach(vdata_id); + free(h5cvdata_name); + free(cor_cvdataname); + return FAIL; + } + free(cor_cvdataname); + if(H5Glink(h5_pgroup,H5G_LINK_HARD,h5cvdata_name,h5lvdata_name)){ + printf("error in creating hardlink for hdf5 dataset"); + printf(" converted from vdata.\n"); + VSdetach(vdata_id); + free(h5cvdata_name); + free(h5lvdata_name); + return FAIL; + } + free(h5cvdata_name); + free(h5lvdata_name); + } + VSdetach(vdata_id); + } + + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: convert_sds + * + * Purpose: subroutine interface for better modularity of vgroup_h4_to_h5 + * In this routine, 1) h5 sds name is obtained; + 2) sds_h4_to_h5 is called for unvisited + sds objects + 3) HardLink is created for visited sds + + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + sd_id: hdf4 sds identifier + obj_ref: object reference number + h5_dimgroup: h5 dimensional scale group id + h5_pgroup: hdf5 group id + + *------------------------------------------------------------------------- + */ +int convert_sds(int32 file_id,int32 sd_id,int32 obj_ref,char * h5pgroup_name, + hid_t h5_pgroup,hid_t h5_dimgroup) { + + int32 sd_index; + int32 sds_id; + int32 sds_rank; + int32 sds_dimsizes[DIM_HASHSIZE]; + int32 sds_dtype; + int32 num_sdsattrs; + char sds_name[MAX_NC_NAME]; + char* cor_sdsname; + int check_sds; + int check_sdsname; + char refstr[MAXREF_LENGTH]; + char* h5csds_name; + char* h5lsds_name; + + sd_index = SDreftoindex(sd_id,obj_ref); + if(sd_index == FAIL){ + printf("error in obtaining reference number of sds.\n"); + return FAIL; + } + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("error in converting reference number into string type.\n"); + return FAIL; + } + + sds_id = SDselect(sd_id,sd_index); + + if(sds_id == FAIL){ + printf("error in obtaining sd id.\n"); + return FAIL; + } + + if(SDgetinfo(sds_id,sds_name,&sds_rank,sds_dimsizes, + &sds_dtype,&num_sdsattrs)==FAIL) { + printf("error in obtaining SD info.\n"); + SDendaccess(sds_id); + return FAIL; + } + + /* check whether this sds is touched. */ + check_sds = lookup(obj_ref,2*num_sds,sds_hashtab); + + cor_sdsname = correct_name(sds_name); + if(cor_sdsname == NULL) { + printf("error in generating corrected sds name. \n"); + SDendaccess(sds_id); + return FAIL; + } + + if(check_sds == 0) { + + /* obtain the absolute name of sds object, deal with the name clashing by + looking up things in the "name hashing table".*/ + + h5csds_name = get_obj_aboname(cor_sdsname,refstr,h5pgroup_name,HDF4_SDS); + if(h5csds_name == NULL) { + printf("error in obtaining sds name.\n"); + SDendaccess(sds_id); + free(cor_sdsname); + return FAIL; + } + free(cor_sdsname); + + /* put the absolute path of sds into "hashing table".*/ + if(set_name(obj_ref,2*num_sds,sds_hashtab,h5csds_name)==FAIL) { + printf("error in setting object name.\n"); + SDendaccess(sds_id); + free(h5csds_name); + return FAIL; + } + /* convert the sds object into hdf5 dataset.*/ + if(Sds_h4_to_h5(file_id,sds_id,h5_pgroup,h5_dimgroup)==FAIL){ + printf("error in translating sds into hdf5 dataset.\n"); + SDendaccess(sds_id); + free(h5csds_name); + return FAIL; + } + free(h5csds_name); + } + else { + /* if the object has been touched, create a hard link instead.*/ + h5csds_name = get_name(obj_ref,2*num_sds,sds_hashtab,&check_sdsname); + if(h5csds_name == NULL) { + printf("error in getting sds name \n"); + SDendaccess(sds_id); + return FAIL; + } + /*... ADD in the code. create HL, + for the time being, we will use absolute path. */ + h5lsds_name = get_obj_aboname(cor_sdsname,refstr,h5pgroup_name, + HDF4_SDS); + if(h5lsds_name == NULL) { + printf("error in getting sds link name.\n"); + SDendaccess(sds_id); + free(h5csds_name); + free(cor_sdsname); + return FAIL; + } + free(cor_sdsname); + if(H5Glink(h5_pgroup,H5G_LINK_HARD,h5csds_name,h5lsds_name) <0) { + printf("error in getting hard link \n"); + SDendaccess(sds_id); + free(h5csds_name); + free(h5lsds_name); + return FAIL; + } + + free(h5csds_name); + free(h5lsds_name); + } + SDendaccess(sds_id); + return SUCCEED; +} + +/*------------------------------------------------------------------------- + * Function: convert_image + * + * Purpose: subroutine interface for better modularity of vgroup_h4_to_h5 + * In this routine, 1) h5 vdata name is obtained; + 2) image_h4_to_h5 is called for unvisited + images + 3) Hard Link is created for visited images + + * Return: FAIL if failed, SUCCEED if successful. + * + * In : + file_id: hdf4 file identifier + obj_ref: object reference number + h5pgroup_name: h5 group name + h5_pgroup: hdf5 group id + h5_palgroup: hdf5 palette group id + + *------------------------------------------------------------------------- + */ +int convert_image(int32 file_id,int32 obj_ref,char * h5pgroup_name, + hid_t h5_pgroup,hid_t h5_palgroup) { + + int32 gr_id; + int32 gr_index; + int32 ri_id; + int32 istat; + char* h5cimage_name; + char* h5limage_name; + char refstr[MAXREF_LENGTH]; + char image_name[MAX_GR_NAME]; + char* cor_imagename; + + int check_imagename; + int check_image; + + + gr_id = GRstart(file_id); + if(gr_id == FAIL) { + printf("error in obtaining gr id. \n"); + return FAIL; + } + + if(conv_int_str(obj_ref,refstr)== FAIL) { + printf("converting integer into string format.\n"); + return FAIL; + } + + gr_index= GRreftoindex(gr_id,obj_ref); + if(gr_index == FAIL) { + printf("error in getting gr index.\n"); + return FAIL; + } + + ri_id = GRselect(gr_id,gr_index); + if(ri_id == FAIL) { + printf("error in selecting gr interface.\n"); + return FAIL; + } + + istat = GRgetiminfo(ri_id, image_name, NULL, NULL, NULL, NULL, NULL); + + if(istat == FAIL) { + GRendaccess(ri_id); + printf("error in getting GR images.\n"); + return FAIL; + } + + /* checking whether image name contains ORI_SLASH, + changing into CHA_SLASH.*/ + + cor_imagename = correct_name(image_name); + if(cor_imagename == NULL) { + printf("error in generating corrected image name. \n"); + GRendaccess(ri_id); + return FAIL; + } + + /* check whether this image is touched. */ + check_image = lookup(obj_ref,2*num_images,gr_hashtab); + + if(check_image == 0) { + + /* obtain the absolute name of image object, deal with the name clashing by + looking up things in the "name hashing table".*/ + + h5cimage_name = get_obj_aboname(cor_imagename,refstr,h5pgroup_name, + HDF4_IMAGE); + if(h5cimage_name == NULL) { + printf("error in getting image name.\n"); + GRendaccess(ri_id); + free(cor_imagename); + return FAIL; + } + free(cor_imagename); + + if(set_name(obj_ref,2*num_images,gr_hashtab,h5cimage_name)==FAIL) { + printf("error setting image name.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + return FAIL; + } + if(Image_h4_to_h5(file_id,ri_id,h5_pgroup,h5_palgroup)==FAIL) { + printf("error in transferring image name into hdf5 dataset.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + return FAIL; + } + free(h5cimage_name); + } + + else{ + + /*if the object is visited, create HL. */ + + h5cimage_name = get_name(obj_ref,2*num_images,gr_hashtab, + &check_imagename); + + if(h5cimage_name == NULL) { + printf("error in getting image name into hdf5 dataset.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + return FAIL; + } + h5limage_name = get_obj_aboname(cor_imagename,refstr,h5pgroup_name, + HDF4_IMAGE); + + if(h5limage_name == NULL) { + printf("error in getting link image name into hdf5 dataset.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + free(cor_imagename); + return FAIL; + } + free(cor_imagename); + + if(H5Glink(h5_pgroup,H5G_LINK_HARD,h5cimage_name,h5limage_name)<0){ + printf("error in linking two groups.\n"); + GRendaccess(ri_id); + free(h5cimage_name); + free(h5limage_name); + return FAIL; + } + free(h5cimage_name); + free(h5limage_name); + } + + GRendaccess(ri_id); + /* this is for efficient reason, we will comment out GRend. + GRend(gr_id);*/ + + return SUCCEED; +} + + + + + diff --git a/tools/h4toh5/testh4toh5.sh b/tools/h4toh5/testh4toh5.sh new file mode 100755 index 0000000..c2a196e --- /dev/null +++ b/tools/h4toh5/testh4toh5.sh @@ -0,0 +1,249 @@ +#!/bin/sh +# +# Copyright (C) 2001 National Center for Supercomputing Applications. +# All rights reserved. +# +# Test script for the h4toh5 tests. +# Using the h4toh5 convert to convert a pre-created hdf file to +# an hdf5 file (output file), then compare it with a pre-created +# corresponding hdf5 file (expected file). +# If the same, that particular test passes. +# If not the same, the output file and expected file are processed +# by the h5dump tool to see if they produce the same results. +# If the same, the test passes. +# If not, show the difference of the two results and report the test failed. +# +# h5dump is default to use the one just built. It can be overridden +# by setting $H5DUMP to a different value such as /usr/local/bin/h5dump. + +H4TOH5=h4toh5 # The tool name +H4TOH5_BIN=`pwd`/$H4TOH5 # The path of the tool binary + +CMP='cmp -s' +DIFF='diff -c' + +RM='rm -f' +SED='sed ' +H5DUMP=${H5DUMP:-`pwd`/'../h5dump/h5dump'} # Default to use the h5dumper + # in the same tools directory + +# Verify if $H5DUMP is a valid command. +tmpfile=/tmp/testh4toh5.$$ +$H5DUMP -V > $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 --- /dev/null +++ b/tools/h5dump/Dependencies 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 <stdio.h> +#include <stdlib.h> + +#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 */ + "</HDF5-File>", /*fileend */ + "", /*bootblockbegin */ + "", /*bootblockend */ + "", /*groupbegin */ + "</Group>", /*groupend */ + "", /*datasetbegin */ + "</Dataset>", /*datasetend */ + "", /*attributebegin */ + "</Attribute>", /*attributeend */ + "<DataType>", /*datatypeend */ + "</DataType>", /*datatypeend */ + "<Dataspace>", /*dataspacebegin */ + "</Dataspace>", /*dataspaceend */ + "<Data>", /*databegin */ + "</Data>", /*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("<SoftLink LinkName=\"%s\" Target=\"%s\" " + "TargetObj=\"%s\" OBJ-XID=\"%s\" Source=\"%s\"/>\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("<Dataset Name=\"%s\" OBJ-XID=\"%s\" Parents=\"%s\">\n", + t_name, t_tmp, + (strcmp(prefix, "") ? t_prefix : "root")); + + indentation(indent + COL); + printf("<DatasetPtr OBJ-XID=\"%s\"/>\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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + printf("<!DOCTYPE HDF5-File PUBLIC \"HDF5-File.dtd\" \"%s\">\n", + xml_dtd_uri); + printf("<HDF5-File>\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 <empty>", 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 <DataType> 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("<AtomicType>\n"); + indent += COL; + /* <IntegerType ByteOrder="bo" Sign="torf" Size="bytes"/> */ + ord = H5Tget_order(type); + sgn = H5Tget_sign(type); + indentation(indent); + printf("<IntegerType ByteOrder=\""); + switch (ord) { + case H5T_ORDER_LE: + printf("LE"); + break; + case H5T_ORDER_BE: + printf("BE"); + break; + case H5T_ORDER_VAX: + default: + printf("ERROR_UNKNOWN"); + } + printf("\" Sign=\""); + switch (sgn) { + case H5T_SGN_NONE: + printf("false"); + break; + case H5T_SGN_2: + printf("true"); + break; + default: + printf("ERROR_UNKNOWN"); + } + printf("\" Size=\""); + sz = H5Tget_size(type); + printf("%d", sz); + printf("\" />\n"); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_FLOAT: + /* <FloatType ByteOrder="bo" Size="bytes" + SignBitLocation="bytes" + ExponentBits="eb" ExponentLocation="el" + MantissaBits="mb" MantissaLocation="ml" /> */ + ord = H5Tget_order(type); + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<FloatType ByteOrder=\""); + switch (ord) { + case H5T_ORDER_LE: + printf("LE"); + break; + case H5T_ORDER_BE: + printf("BE"); + break; + case H5T_ORDER_VAX: + default: + printf("ERROR_UNKNOWN"); + } + printf("\" Size=\""); + sz = H5Tget_size(type); + printf("%d", sz); + H5Tget_fields(type, &spos, &epos, &esize, &mpos, &msize); + printf("\" SignBitLocation=\"%d\" ", spos); + printf("ExponentBits=\"%d\" ExponentLocation=\"%d\" ", esize, epos); + printf("MantissaBits=\"%d\" MantissaLocation=\"%d\" />\n", + msize, mpos); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_TIME: + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<TimeType />\n"); + printf("<!-- H5T_TIME: not yet implemented -->"); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_STRING: + /* <StringType Cset="cs" StrSize="chars" StrPad="pad" /> */ + size = H5Tget_size(type); + str_pad = H5Tget_strpad(type); + cset = H5Tget_cset(type); + + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<StringType Cset=\""); + if (cset == H5T_CSET_ASCII) { + printf("H5T_CSET_ASCII\" "); + } else { + printf("unknown_cset\" "); + } + printf("StrSize=\"%d\" StrPad=\"", (int) size); + 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"); + } + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_BITFIELD: + /* <BitfieldType ByteOrder="bo" Size="bytes"/> */ + ord = H5Tget_order(type); + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<BitfieldType ByteOrder=\""); + switch (ord) { + case H5T_ORDER_LE: + printf("LE"); + break; + case H5T_ORDER_BE: + printf("BE"); + break; + case H5T_ORDER_VAX: + default: + printf("ERROR_UNKNOWN"); + } + size = H5Tget_size(type); + printf("\" Size=\"%d\"/>\n", size); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_OPAQUE: + /* <OpaqueType Tag="tag" Size="bytes" /> */ + + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<OpaqueType Tag=\"%s\" ", H5Tget_tag(type)); + size = H5Tget_size(type); + printf("Size=\"%d\"/>\n", size); + indent -= COL; + indentation(indent); + printf("</AtomicType>\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("<NamedDataTypePtr OBJ-XID=\"/#%lu:%lu\"/>\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("<NamedDataTypePtr OBJ-XID=\"%s\"/>\n", t_objname); + free(t_objname); + } + } else { + printf("<!-- h5dump error: unknown committed type. -->\n"); + d_status = EXIT_FAILURE; + } + + } else { + /* type of a dataset */ + nmembers = H5Tget_nmembers(type); + + indentation(indent); + printf("<CompoundType>\n"); + + /* List each member Field of the type */ + /* <Field FieldName="name" > */ + /* <DataType > */ + 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("<Field FieldName=\"%s\">\n", t_fname); + + free(fname); + free(t_fname); + indent += COL; + indentation(indent); + printf("<DataType>\n"); + indent += COL; + xml_print_datatype(mtype); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + + indentation(indent); + printf("</Field>\n"); + } + indent -= COL; + indentation(indent); + printf("</CompoundType>\n"); + } + break; + + case H5T_REFERENCE: + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + /* Only Object references supported at this time */ + printf("<ReferenceType>\n"); + indentation(indent + COL); + printf("<ObjectReferenceType />\n"); + indentation(indent); + printf("</ReferenceType>\n"); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_ENUM: + /* <EnumType Nelems="ne" > + list Name, values of enum + */ + nmembs = H5Tget_nmembers(type); + indentation(indent); + printf("<AtomicType>\n"); + indent += COL; + indentation(indent); + printf("<EnumType Nelems=\"%d\">\n", nmembs); + xml_print_enum(type); + indentation(indent); + printf("</EnumType>\n"); + indent -= COL; + indentation(indent); + printf("</AtomicType>\n"); + break; + + case H5T_VLEN: + indentation(indent); + printf("<VLType>\n"); + super = H5Tget_super(type); + indent += COL; + indentation(indent); + printf("<DataType>\n"); + indent += COL; + xml_print_datatype(super); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + indentation(indent); + printf("</VLType>\n"); + H5Tclose(super); + + break; + + case H5T_ARRAY: + /* Get array base type */ + super = H5Tget_super(type); + + /* Print lead-in */ + indentation(indent); + printf("<ArrayType Ndims=\""); + ndims = H5Tget_array_ndims(type); + printf("%d\">\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("<ArrayDimension DimSize=\"%u\" DimPerm=\"%u\"/>\n", + (int) dims[j], (int) perm[j]); + } + } else { + for (j = 0; j < ndims; j++) { + indentation(indent); + printf("<ArrayDimension DimSize=\"%u\" DimPerm=\"0\"/>\n", + (int) dims[j]); + } + } + indent -= COL; + + indent += COL; + indentation(indent); + printf("<DataType>\n"); + indent += COL; + xml_print_datatype(super); + indent -= COL; + indentation(indent); + printf("%s\n", dump_header_format->datatypeend); + indent -= COL; + indentation(indent); + printf("</ArrayType>\n"); + /* Close array base type */ + H5Tclose(super); + break; + + default: + printf("<!-- unknown data type -->"); + 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("<NamedDataTypePtr OBJ-XID=\"/#%lu:%lu\"/>\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("<NamedDataTypePtr OBJ-XID=\"%s\"/>\n", t_objname); + free(t_objname); + } + } else { + printf("<!-- h5dump error: unknown committed type. -->\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("<ScalarDataspace />\n"); + } else { + /* simple dataspace */ + /* <SimpleDataspace Ndims="nd"> */ + printf("<SimpleDataspace Ndims=\"%d\">\n", ndims); + + /* print the <Dimension> elements */ + for (i = 0; i < ndims; i++) { + indentation(indent + COL + COL + COL); + if (maxsize[i] == H5S_UNLIMITED) { + HDfprintf(stdout, + "<Dimension DimSize=\"%Hu\" MaxDimSize=\"UNLIMITED\"/>\n", + size[i]); + } else if (maxsize[i] == (hsize_t) 0) { + HDfprintf(stdout, + "<Dimension DimSize=\"%Hu\" MaxDimSize=\"%Hu\"/>\n", + size[i], size[i]); + } else { + HDfprintf(stdout, + "<Dimension DimSize=\"%Hu\" MaxDimSize=\"%Hu\"/>\n", + size[i], maxsize[i]); + } + } + indentation(indent + COL + COL); + printf("</SimpleDataspace>\n"); + } + } else { + printf("<!-- not yet implemented -->\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("<DataFromFile>\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("</DataFromFile>\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("<Attribute Name=\"%s\">\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("<Data>\n"); + indentation(indent); + printf("<!-- Time data not yet implemented. -->\n"); + indentation(indent); + printf("<NoData />\n"); + indentation(indent); + printf("<Data>\n"); + indent -= COL; + break; + + case H5T_COMPOUND: + indentation(indent); + printf("<!-- Note: format of compound data not specified -->\n"); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA); + break; + + case H5T_REFERENCE: + indentation(indent); + printf("<Data>\n"); + indentation(indent); + printf("<DataFromFile>\n"); + xml_print_refs(attr_id, ATTRIBUTE_DATA); + indentation(indent); + printf("</DataFromFile>\n"); + indentation(indent); + printf("</Data>\n"); + break; + + case H5T_VLEN: + printf("<!-- Note: format of VL data not specified -->\n"); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA); + break; + default: + indentation(indent); + printf("<Data>\n"); + indentation(indent); + printf("<!-- Unknown datatype: %d -->\n", H5Tget_class(type)); + indentation(indent); + printf("<NoData/>\n"); + indentation(indent); + printf("</Data>\n"); + break; + } + } else { + /* The case of an attribute never yet written ?? */ + indentation(indent); + printf("<Data>\n"); + indentation(indent + COL); + printf("<NoData/>\n"); + indentation(indent); + printf("</Data>\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("<!-- h5dump error: unable to open attribute. -->\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("<NamedDataType Name=\"%s\" OBJ-XID=\"%s\" Parents=\"%s\">\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("<NamedDataType Name=\"%s\" OBJ-XID=\"%s\" Parents=\"%s\">\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("<CompoundType>\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("<Field FieldName=\"%s\">\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("</Field>\n"); + } + + indent -= COL; + indentation(indent); + printf("</CompoundType>\n"); + } else { + /* Other data types: call print_datatype */ + indent += COL; + xml_print_datatype(type); + indent -= COL; + } + + indent -= COL; + indentation(indent); + printf("</NamedDataType>\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("<RootGroup OBJ-XID=\"root\">\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("<Group Name=\"%s\" OBJ-XID=\"%s\" Parents=\"%s\" >\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("<GroupPtr OBJ-XID=\"%s\"/>\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("</RootGroup>\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("<Compression />\n"); + indentation(indent + COL); + printf("<!-- Compression parameter %d -->\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("<Dataset Name=\"%s\" OBJ-XID=\"%s\" Parents=\"%s\">\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("<StorageLayout>\n"); + indent += COL; + indentation(indent); + printf("<ChunkedLayout "); + ndims = H5Pget_chunk(dcpl, maxdims, chsize); + printf("Ndims=\"%d\">\n", ndims); + /* check for compression and tell about it... */ + + check_compression(dcpl); + + indent += COL; + + for (i = 0; i < ndims; i++) { + indentation(indent); + HDfprintf(stdout, "<ChunkDimension DimSize=\"%Hu\" />\n", chsize[i]); + } + + indent -= COL; + + indentation(indent); + printf("</ChunkedLayout>\n"); + indent -= COL; + indentation(indent); + printf("</StorageLayout>\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("<Data>\n"); + indentation(indent); + printf("<!-- Time data not yet implemented. -->\n"); + indentation(indent); + printf("<NoData />\n"); + indentation(indent); + printf("<Data>\n"); + indent -= COL; + break; + + case H5T_COMPOUND: + indentation(indent); + printf("<!-- Note: format of compound data not specified -->\n"); + dump_function_table->dump_data_function(did, DATASET_DATA); + break; + + case H5T_REFERENCE: + indentation(indent); + printf("<Data>\n"); + indentation(indent); + printf("<DataFromFile>\n"); + xml_print_refs(did, DATASET_DATA); + indentation(indent); + printf("</DataFromFile>\n"); + indentation(indent); + printf("</Data>\n"); + break; + + case H5T_VLEN: + printf("<!-- Note: format of VL data not specified -->\n"); + dump_function_table->dump_data_function(did, DATASET_DATA); + break; + default: + indentation(indent); + printf("<Data>\n"); + indentation(indent); + printf("<!-- Unknown datatype: %d -->\n", H5Tget_class(type)); + indentation(indent); + printf("<NoData/>\n"); + indentation(indent); + printf("</Data>\n"); + break; + } + } else { + /* no data written */ + indentation(indent); + printf("<Data>\n"); + indentation(indent); + printf("<NoData/>\n"); + indentation(indent); + printf("</Data>\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("<EnumElement>\n"); + indentation(indent + COL); + printf("%s\n", t_name); + free(t_name); + indentation(indent); + printf("</EnumElement>\n"); + indentation(indent); + printf("<EnumValue>\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("</EnumValue>\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 <limits.h> +#include "hdf5.h" +#include <H5private.h> + +#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; i<SPACE1_DIM1; i++) + *tu32++=i*3; + + /* Write selection to disk */ + H5Dwrite(dataset,H5T_NATIVE_UINT,H5S_ALL,H5S_ALL,H5P_DEFAULT,wbuf); + + /* Close Dataset */ + H5Dclose(dataset); + + /* Create another dataset (inside Group1) */ + dataset=H5Dcreate(group,"Dataset2",H5T_STD_U8BE,sid1,H5P_DEFAULT); + + /* Close Dataset */ + H5Dclose(dataset); + + /* Create a datatype to refer to */ + tid1 = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + + /* Insert fields */ + H5Tinsert (tid1, "a", HOFFSET(s1_t,a), H5T_STD_I32BE); + + H5Tinsert (tid1, "b", HOFFSET(s1_t,b), H5T_IEEE_F32BE); + + H5Tinsert (tid1, "c", HOFFSET(s1_t,c), H5T_IEEE_F32BE); + + /* Save datatype for later */ + H5Tcommit (group, "Datatype1", tid1); + + /* Close datatype */ + H5Tclose(tid1); + + /* Close group */ + H5Gclose(group); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset3",H5T_STD_REF_OBJ,sid1,H5P_DEFAULT); + + /* Create reference to dataset */ + H5Rcreate(&wbuf[0],fid1,"/Group1/Dataset1",H5R_OBJECT,-1); + H5Rget_object_type(dataset,&wbuf[0]); + + /* Create reference to dataset */ + H5Rcreate(&wbuf[1],fid1,"/Group1/Dataset2",H5R_OBJECT,-1); + + H5Rget_object_type(dataset,&wbuf[1]); + + /* Create reference to group */ + H5Rcreate(&wbuf[2],fid1,"/Group1",H5R_OBJECT,-1); + + H5Rget_object_type(dataset,&wbuf[2]); + + + /* Create reference to named datatype */ + H5Rcreate(&wbuf[3],fid1,"/Group1/Datatype1",H5R_OBJECT,-1); + + H5Rget_object_type(dataset,&wbuf[3]); + + + /* Write selection to disk */ + H5Dwrite(dataset,H5T_STD_REF_OBJ,H5S_ALL,H5S_ALL,H5P_DEFAULT,wbuf); + + + /* Close disk dataspace */ + H5Sclose(sid1); + + /* Close Dataset */ + H5Dclose(dataset); + + /* Close file */ + H5Fclose(fid1); + + /* Free memory buffers */ + free(wbuf); + free(rbuf); + free(tbuf); + +} + +static void test_datareg(void) +{ + /*some code is taken from enum.c in the test dir */ + + hid_t fid1; /* HDF5 File IDs */ + hid_t dset1, /* Dataset ID */ + dset2; /* Dereferenced dataset ID */ + hid_t sid1, /* Dataspace ID #1 */ + sid2; /* Dataspace ID #2 */ + hsize_t dims1[] = {SPACE1_DIM1}, + dims2[] = {SPACE2_DIM1, SPACE2_DIM2}; + hssize_t start[SPACE2_RANK]; /* Starting location of hyperslab */ + hsize_t stride[SPACE2_RANK]; /* Stride of hyperslab */ + hsize_t count[SPACE2_RANK]; /* Element count of hyperslab */ + hsize_t block[SPACE2_RANK]; /* Block size of hyperslab */ + hssize_t coord1[POINT1_NPOINTS][SPACE2_RANK]; /* Coordinates for point selection */ + hdset_reg_ref_t *wbuf, /* buffer to write to disk */ + *rbuf; /* buffer read from disk */ + uint8_t *dwbuf, /* Buffer for writing numeric data to disk */ + *drbuf; /* Buffer for reading numeric data from disk */ + uint8_t *tu8; /* Temporary pointer to uint8 data */ + intn i; /* counting variables */ + + /* Allocate write & read buffers */ + wbuf=calloc(sizeof(hdset_reg_ref_t), SPACE1_DIM1); + rbuf=malloc(sizeof(hdset_reg_ref_t)*SPACE1_DIM1); + dwbuf=malloc(sizeof(uint8_t)*SPACE2_DIM1*SPACE2_DIM2); + drbuf=calloc(sizeof(uint8_t),SPACE2_DIM1*SPACE2_DIM2); + + /* Create file */ + fid1 = H5Fcreate(FILE17, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid2 = H5Screate_simple(SPACE2_RANK, dims2, NULL); + + /* Create a dataset */ + dset2=H5Dcreate(fid1,"Dataset2",H5T_STD_U8BE,sid2,H5P_DEFAULT); + + for(tu8=dwbuf,i=0; i<SPACE2_DIM1*SPACE2_DIM2; i++) + *tu8++=i*3; + + /* Write selection to disk */ + H5Dwrite(dset2,H5T_NATIVE_UCHAR,H5S_ALL,H5S_ALL,H5P_DEFAULT,dwbuf); + + /* Close Dataset */ + H5Dclose(dset2); + + /* Create dataspace for the reference dataset */ + sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); + + /* Create a dataset */ + dset1=H5Dcreate(fid1,"Dataset1",H5T_STD_REF_DSETREG,sid1,H5P_DEFAULT); + + /* Create references */ + + /* Select 6x6 hyperslab for first reference */ + start[0]=2; start[1]=2; + stride[0]=1; stride[1]=1; + count[0]=6; count[1]=6; + block[0]=1; block[1]=1; + H5Sselect_hyperslab(sid2,H5S_SELECT_SET,start,stride,count,block); + + H5Sget_select_npoints(sid2); + + /* Store first dataset region */ + H5Rcreate(&wbuf[0],fid1,"/Dataset2",H5R_DATASET_REGION,sid2); + + /* Select sequence of ten points for second reference */ + coord1[0][0]=6; coord1[0][1]=9; + coord1[1][0]=2; coord1[1][1]=2; + coord1[2][0]=8; coord1[2][1]=4; + coord1[3][0]=1; coord1[3][1]=6; + coord1[4][0]=2; coord1[4][1]=8; + coord1[5][0]=3; coord1[5][1]=2; + coord1[6][0]=0; coord1[6][1]=4; + coord1[7][0]=9; coord1[7][1]=0; + coord1[8][0]=7; coord1[8][1]=1; + coord1[9][0]=3; coord1[9][1]=3; + H5Sselect_elements(sid2,H5S_SELECT_SET,POINT1_NPOINTS,(const hssize_t **)coord1); + + H5Sget_select_npoints(sid2); + + /* Store second dataset region */ + H5Rcreate(&wbuf[1],fid1,"/Dataset2",H5R_DATASET_REGION,sid2); + + /* Write selection to disk */ + H5Dwrite(dset1,H5T_STD_REF_DSETREG,H5S_ALL,H5S_ALL,H5P_DEFAULT,wbuf); + + /* Close disk dataspace */ + H5Sclose(sid1); + + /* Close Dataset */ + H5Dclose(dset1); + + /* Close uint8 dataset dataspace */ + H5Sclose(sid2); + + /* Close file */ + H5Fclose(fid1); + + /* Free memory buffers */ + free(wbuf); + free(rbuf); + free(dwbuf); + free(drbuf); +} + +/*taken from Elena's compound test file*/ +static void test_nestcomp(void) +{ + /* Compound memeber of the compound datatype*/ + typedef struct cmp_t { + char a; + float b[2]; + } cmp_t; + + /* First structure and dataset*/ + typedef struct s1_t { + int a; + float b; + double c; + cmp_t d; + } s1_t; + hid_t cmp_tid; /* Handle for the compound datatype */ + hid_t char_id; /* Handle for the string datatype */ + hid_t array_dt; + hsize_t array_dims[] = {2}; /* Dataspace dimensions */ + int ndims = 1; /* Number of dimensions in the array field */ + + s1_t s1[10]; + hid_t s1_tid; /* File datatype identifier */ + + int i; + hid_t file, dataset, space; /* Handles */ + herr_t status; + hsize_t dim[] = {10}; /* Dataspace dimensions */ + + char datasetname[] = "ArrayOfStructures"; + + + /* + * Initialize the data + */ + for (i = 0; i< 10; i++) { + s1[i].a = i; + s1[i].b = i*i; + s1[i].c = 1./(i+1); + s1[i].d.a = 65 + i; + s1[i].d.b[0] = -100.; + s1[i].d.b[1] = 100.; + } + + /* + * Create the data space. + */ + space = H5Screate_simple(1, dim, NULL); + + /* + * Create the file. + */ + file = H5Fcreate(FILE18, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create the memory data type. + */ + /* + * Create a datatype for compound field first. + */ + cmp_tid = H5Tcreate (H5T_COMPOUND, sizeof(cmp_t)); + + /* We are using C string of length one to represent "real" character */ + char_id = H5Tcopy(H5T_C_S1); + H5Tset_strpad(char_id, H5T_STR_NULLTERM); + H5Tinsert(cmp_tid, "char_name", HOFFSET(cmp_t, a), char_id); + + array_dt=H5Tarray_create(H5T_NATIVE_FLOAT,ndims,array_dims,NULL); + H5Tinsert(cmp_tid, "array_name", HOFFSET(cmp_t, b), array_dt); + H5Tclose(array_dt); + + s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT); + H5Tinsert(s1_tid, "c_name", HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), H5T_NATIVE_FLOAT); + + /* Insert compound memeber created above */ + H5Tinsert(s1_tid, "d_name", HOFFSET(s1_t, d), cmp_tid); + + /* + * Create the dataset. + */ + dataset = H5Dcreate(file, datasetname, s1_tid, space, H5P_DEFAULT); + + /* + * Wtite data to the dataset; + */ + status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1); + if (status < 0) + fprintf(stderr, "test_nestcomp H5Dwrite failed\n"); + + /* + * Release resources + */ + H5Tclose(s1_tid); + H5Tclose(cmp_tid); + H5Tclose(char_id); + H5Sclose(space); + H5Dclose(dataset); + H5Fclose(file); +} + +static void test_opaque(void) +{ + hid_t file, type, dataset, space; + char test[100][2]; + int x; + hsize_t dim = 2; + + for (x = 0; x < 100; x++){ + test[x][0] = x; + test[x][1] = 99 - x; + } + + /* + * Create the data space. + */ + space = H5Screate_simple(1, &dim, NULL); + + /* + * Create the file. + */ + file = H5Fcreate(FILE19, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create the memory datatype. + */ + type = H5Tcreate (H5T_OPAQUE, sizeof(char)*100*2); + H5Tset_tag(type, "test opaque type"); + + /* + * Create the dataset. + */ + dataset = H5Dcreate(file, "opaque test", type, space, H5P_DEFAULT); + + /* + * Write data to the dataset; + */ + H5Dwrite(dataset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, test); + + H5Tclose(type); + H5Sclose(space); + H5Dclose(dataset); + H5Fclose(file); +} + +static void test_bitfields(void) +{ + hid_t file, grp=-1, type=-1, space=-1, dset=-1; + size_t i; + hsize_t nelmts; + unsigned char buf[32]; + + file = H5Fcreate(FILE20, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + if ((grp=H5Gcreate(file, "typetests", 0))<0) goto error; + + /* bitfield_1 */ + nelmts = sizeof(buf); + if ((type=H5Tcopy(H5T_STD_B8LE))<0 || + (space=H5Screate_simple(1, &nelmts, NULL))<0 || + (dset=H5Dcreate(grp, "bitfield_1", type, space, H5P_DEFAULT))<0) + goto error; + + for (i=0; i<sizeof buf; i++) buf[i] = (unsigned char)0xff ^ (unsigned char)i; + if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf)<0) + goto error; + if (H5Sclose(space)<0) goto error; + if (H5Tclose(type)<0) goto error; + if (H5Dclose(dset)<0) goto error; + + /* bitfield_2 */ + nelmts = sizeof(buf)/2; + if ((type=H5Tcopy(H5T_STD_B16LE))<0 || + (space=H5Screate_simple(1, &nelmts, NULL))<0 || + (dset=H5Dcreate(grp, "bitfield_2", type, space, H5P_DEFAULT))<0) + goto error; + for (i=0; i<sizeof buf; i++) buf[i] = (unsigned char)0xff ^ (unsigned char)i; + if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf)<0) + goto error; + if (H5Sclose(space)<0) goto error; + if (H5Tclose(type)<0) goto error; + if (H5Dclose(dset)<0) goto error; + if (H5Gclose(grp)<0) goto error; + H5Fclose(file); + + error: + H5E_BEGIN_TRY { + H5Gclose(grp); + H5Tclose(type); + H5Sclose(space); + H5Dclose(dset); + } H5E_END_TRY; +} + +static void test_vldatatypes(void) +{ + hvl_t adata, wdata[SPACE1_DIM1]; + hid_t file, dset, space, type; + hsize_t dims[] = { SPACE1_DIM1 }; + int i; + herr_t ret=0; + + ret = ret; /* so that compiler won't complain "is set but never used" */ + file = H5Fcreate(FILE21, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Allocate and initialize VL dataset to write */ + for(i = 0; i < SPACE1_DIM1; i++) { + int j; + + wdata[i].p = malloc((i + 1) * sizeof(int)); + wdata[i].len = i + 1; + + for (j = 0; j < i + 1; j++) + ((int *)wdata[i].p)[j] = i * 10 + j; + } + + /* write out the integers in little-endian format */ + space = H5Screate_simple(SPACE1_RANK, dims, NULL); + type = H5Tvlen_create(H5T_NATIVE_INT); + dset = H5Dcreate(file, "Dataset1.0", type, space, H5P_DEFAULT); + ret = H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); + ret = H5Dvlen_reclaim(type, space, H5P_DEFAULT, wdata); + + ret = H5Dclose(dset); + ret = H5Tclose(type); + ret = H5Sclose(space); + + /* Allocate and initialize VL dataset to write */ + for(i = 0; i < SPACE1_DIM1; i++) { + int j; + + wdata[i].p = malloc((i + 1) * sizeof(float)); + wdata[i].len = i + 1; + + for (j = 0; j < i + 1; j++) + ((float *)wdata[i].p)[j] = i * 10 + ((float)j) / 10.0; + } + + /* write out the floats in little-endian format */ + space = H5Screate_simple(SPACE1_RANK, dims, NULL); + type = H5Tvlen_create(H5T_NATIVE_FLOAT); + dset = H5Dcreate(file, "Dataset2.0", type, space, H5P_DEFAULT); + ret = H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); + ret = H5Dvlen_reclaim(type, space, H5P_DEFAULT, wdata); + + ret = H5Dclose(dset); + ret = H5Tclose(type); + ret = H5Sclose(space); + + /* Allocate and initialize a scalar VL dataset to write */ + adata.p = malloc(37 * sizeof(int)); + adata.len = 37; + + for (i = 0; i < 37; i++) + ((int *)adata.p)[i] = i * 2; + + /* write out scalar VL dataset in little-endian format */ + space = H5Screate_simple(0, NULL, NULL); + type = H5Tvlen_create(H5T_NATIVE_INT); + dset = H5Dcreate(file, "Dataset3.0", type, space, H5P_DEFAULT); + ret = H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, &adata); + ret = H5Dvlen_reclaim(type, space, H5P_DEFAULT, &adata); + + ret = H5Dclose(dset); + ret = H5Tclose(type); + ret = H5Sclose(space); + ret = H5Fclose(file); +} + +static void test_vldatatypes2(void) +{ + hvl_t wdata[SPACE1_DIM1]; /* Information to write */ + hvl_t *t1; /* Temporary pointer to VL information */ + 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,k; /* 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<SPACE1_DIM1; i++) { + wdata[i].p=malloc((i+1)*sizeof(hvl_t)); + if(wdata[i].p==NULL) { + printf("Cannot allocate memory for VL data! i=%u\n",i); + return; + } /* end if */ + wdata[i].len=i+1; + for(t1=wdata[i].p,j=0; j<(i+1); j++, t1++) { + t1->p=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<SPACE1_DIM1; i++) { + wdata[i].i=i*10; + wdata[i].f=(i*20)/3.0; + wdata[i].v.p=malloc((i+1)*sizeof(unsigned int)); + wdata[i].v.len=i+1; + for(j=0; j<(i+1); j++) + ((unsigned int *)wdata[i].v.p)[j]=i*10+j; + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE23, 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 compound type */ + tid2 = H5Tcreate(H5T_COMPOUND, sizeof(s1)); + + /* Insert fields */ + ret=H5Tinsert(tid2, "i", HOFFSET(s1, i), H5T_NATIVE_INT); + ret=H5Tinsert(tid2, "f", HOFFSET(s1, f), H5T_NATIVE_FLOAT); + ret=H5Tinsert(tid2, "v", HOFFSET(s1, v), 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_vldatatypes4(void) +{ + typedef struct { /* Struct that the VL sequences are composed of */ + int i; + float f; + } s1; + hvl_t 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<SPACE1_DIM1; i++) { + wdata[i].p=malloc((i+1)*sizeof(s1)); + wdata[i].len=i+1; + for(j=0; j<(i+1); j++) { + ((s1 *)wdata[i].p)[j].i=i*10+j; + ((s1 *)wdata[i].p)[j].f=(i*20+j)/3.0; + } /* end for */ + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE24, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); + + /* Create the base compound type */ + tid2 = H5Tcreate(H5T_COMPOUND, sizeof(s1)); + + /* Insert fields */ + ret=H5Tinsert(tid2, "i", HOFFSET(s1, i), H5T_NATIVE_INT); + ret=H5Tinsert(tid2, "f", HOFFSET(s1, f), H5T_NATIVE_FLOAT); + + /* Create a datatype to refer to */ + tid1 = H5Tvlen_create (tid2); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Tclose(tid2); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_array1(void) +{ + int wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + intn i,j; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Allocate and initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) + wdata[i][j]=i*10+j; + + /* Create file */ + fid1 = H5Fcreate(FILE25, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a datatype to refer to */ + tid1 = H5Tarray_create (H5T_NATIVE_INT,ARRAY1_RANK,tdims1,NULL); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_array2(void) +{ + int wdata[SPACE1_DIM1][ARRAY2_DIM1][ARRAY2_DIM2][ARRAY2_DIM3]; /* Information to write */ + hid_t fid; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid; /* Dataspace ID */ + hid_t tid; /* Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims2[] = {ARRAY2_DIM1,ARRAY2_DIM2,ARRAY2_DIM3}; + intn i,j,k,l; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Allocate and initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY2_DIM1; j++) + for(k=0; k<ARRAY2_DIM2; k++) + for(l=0; l<ARRAY2_DIM3; l++) + wdata[i][j][k][l]=i*1000+j*100+k*10+l; + + /* Create file */ + fid = H5Fcreate(FILE26, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a datatype to refer to */ + tid = H5Tarray_create (H5T_NATIVE_INT,ARRAY2_RANK,tdims2,NULL); + + /* Create a dataset */ + dataset=H5Dcreate(fid,"Dataset1",tid,sid,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid); + ret = H5Sclose(sid); + ret = H5Fclose(fid); +} + +static void test_array3(void) +{ + int wdata[SPACE1_DIM1][ARRAY1_DIM1][ARRAY3_DIM1][ARRAY3_DIM2]; /* Information to write */ + hid_t fid; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid; /* Dataspace ID */ + hid_t tid1; /* 1-D array Datatype ID */ + hid_t tid2; /* 2-D array Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + hsize_t tdims2[] = {ARRAY3_DIM1,ARRAY3_DIM2}; + intn i,j,k,l; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Allocate and initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) + for(k=0; k<ARRAY3_DIM1; k++) + for(l=0; l<ARRAY3_DIM2; l++) + wdata[i][j][k][l]=i*1000+j*100+k*10+l; + + /* Create file */ + fid = H5Fcreate(FILE27, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a 2-D datatype to refer to */ + tid2 = H5Tarray_create (H5T_NATIVE_INT,ARRAY3_RANK,tdims2,NULL); + + /* Create a 1-D datatype to refer to */ + tid1 = H5Tarray_create (tid2,ARRAY1_RANK,tdims1,NULL); + + /* Create a dataset */ + dataset=H5Dcreate(fid,"Dataset1",tid1,sid,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Tclose(tid2); + ret = H5Sclose(sid); + ret = H5Fclose(fid); +} + +static void test_array4(void) +{ + typedef struct { /* Typedef for compound datatype */ + int i; + float f; + } s1_t; + s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Array Datatype ID */ + hid_t tid2; /* Compound Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + intn i,j; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) { + wdata[i][j].i=i*10+j; + wdata[i][j].f=i*2.5+j; + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE28, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a compound datatype to refer to */ + tid2 = H5Tcreate(H5T_COMPOUND, sizeof(s1_t)); + + /* Insert integer field */ + ret = H5Tinsert (tid2, "i", HOFFSET(s1_t,i), H5T_NATIVE_INT); + + /* Insert float field */ + ret = H5Tinsert (tid2, "f", HOFFSET(s1_t,f), H5T_NATIVE_FLOAT); + + /* Create an array datatype to refer to */ + tid1 = H5Tarray_create (tid2,ARRAY1_RANK,tdims1,NULL); + + /* Close compound datatype */ + ret=H5Tclose(tid2); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_array5(void) +{ + typedef struct { /* Typedef for compound datatype */ + int i; + float f[ARRAY1_DIM1]; + } s1_t; + s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Array Datatype ID */ + hid_t tid2; /* Compound Datatype ID */ + hid_t tid3; /* Nested Array Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + intn i,j,k; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) { + wdata[i][j].i=i*10+j; + for(k=0; k<ARRAY1_DIM1; k++) + wdata[i][j].f[k]=i*10+j*2.5+k; + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE29, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a compound datatype to refer to */ + tid2 = H5Tcreate(H5T_COMPOUND, sizeof(s1_t)); + + /* Insert integer field */ + ret = H5Tinsert (tid2, "i", HOFFSET(s1_t,i), H5T_NATIVE_INT); + + /* Create an array of floats datatype */ + tid3 = H5Tarray_create (H5T_NATIVE_FLOAT,ARRAY1_RANK,tdims1,NULL); + + /* Insert float array field */ + ret = H5Tinsert (tid2, "f", HOFFSET(s1_t,f), tid3); + + /* Close array of floats field datatype */ + ret=H5Tclose(tid3); + + /* Create an array datatype to refer to */ + tid1 = H5Tarray_create (tid2,ARRAY1_RANK,tdims1,NULL); + + /* Close compound datatype */ + ret=H5Tclose(tid2); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_array6(void) +{ + hvl_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Array Datatype ID */ + hid_t tid2; /* VL Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + intn i,j,k; /* counting variables */ + herr_t ret; /* Generic return value */ + + /* Initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) { + wdata[i][j].p=malloc((i+j+1)*sizeof(unsigned int)); + wdata[i][j].len=i+j+1; + for(k=0; k<(i+j+1); k++) + ((unsigned int *)wdata[i][j].p)[k]=i*100+j*10+k; + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE30, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create a compound datatype to refer to */ + tid2 = H5Tvlen_create(H5T_NATIVE_UINT); + + /* Create an array datatype to refer to */ + tid1 = H5Tarray_create (tid2,ARRAY1_RANK,tdims1,NULL); + + /* Close VL datatype */ + ret=H5Tclose(tid2); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_array7(void) +{ + hvl_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; /* Information to write */ + hid_t fid1; /* HDF5 File IDs */ + hid_t dataset; /* Dataset ID */ + hid_t sid1; /* Dataspace ID */ + hid_t tid1; /* Array Datatype ID */ + hid_t tid2; /* VL Datatype ID */ + hid_t tid3; /* Nested Array Datatype ID */ + hsize_t sdims1[] = {SPACE1_DIM1}; + hsize_t tdims1[] = {ARRAY1_DIM1}; + intn i,j,k,l; /* Index variables */ + herr_t ret; /* Generic return value */ + + /* Initialize array data to write */ + for(i=0; i<SPACE1_DIM1; i++) + for(j=0; j<ARRAY1_DIM1; j++) { + wdata[i][j].p=malloc((i+j+1)*(sizeof(unsigned int)*ARRAY1_DIM1)); + wdata[i][j].len=i+j+1; + for(k=0; k<(i+j+1); k++) + for(l=0; l<ARRAY1_DIM1; l++) + ((unsigned int *)wdata[i][j].p)[k*ARRAY1_DIM1+l]=i*1000+j*100+k*10+l; + } /* end for */ + + /* Create file */ + fid1 = H5Fcreate(FILE31, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* Create dataspace for datasets */ + sid1 = H5Screate_simple(SPACE1_RANK, sdims1, NULL); + + /* Create the nested array datatype to refer to */ + tid3 = H5Tarray_create(H5T_NATIVE_UINT,ARRAY1_RANK,tdims1,NULL); + + /* Create a VL datatype of 1-D arrays to refer to */ + tid2 = H5Tvlen_create(tid3); + + /* Close nested array datatype */ + ret=H5Tclose(tid3); + + /* Create an array datatype to refer to */ + tid1 = H5Tarray_create (tid2,ARRAY1_RANK,tdims1,NULL); + + /* Close VL datatype */ + ret=H5Tclose(tid2); + + /* Create a dataset */ + dataset=H5Dcreate(fid1,"Dataset1",tid1,sid1,H5P_DEFAULT); + + /* Write dataset to disk */ + ret=H5Dwrite(dataset,tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,wdata); + + /* Reclaim the write VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,wdata); + + /* Close Dataset */ + ret = H5Dclose(dataset); + ret = H5Tclose(tid1); + ret = H5Sclose(sid1); + ret = H5Fclose(fid1); +} + +static void test_empty(void) +{ + typedef struct { + int a; + float b; + char c; + } empty_struct; + hid_t file, dset, space, type; + hsize_t dims[] = { SPACE1_DIM1 }; + herr_t ret=0; + + ret = ret; /* so that compiler won't complain "is set but never used" */ + file = H5Fcreate(FILE32, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + space = H5Screate_simple(SPACE1_RANK, dims, NULL); + + /* write out an empty vlen dataset */ + type = H5Tvlen_create(H5T_NATIVE_INT); + dset = H5Dcreate(file, "Dataset1.0", type, space, H5P_DEFAULT); + /* Don't write any data */ + ret = H5Dclose(dset); + ret = H5Tclose(type); + + /* write out an empty native integer dataset dataset */ + dset = H5Dcreate(file, "Dataset2.0", H5T_NATIVE_INT, space, H5P_DEFAULT); + /* Don't write any data */ + ret = H5Dclose(dset); + + /* write out an empty native floating-point dataset dataset */ + dset = H5Dcreate(file, "Dataset3.0", H5T_NATIVE_FLOAT, space, H5P_DEFAULT); + /* Don't write any data */ + ret = H5Dclose(dset); + + /* write out an empty array dataset */ + type = H5Tarray_create(H5T_NATIVE_INT,SPACE1_RANK,dims,NULL); + dset = H5Dcreate(file, "Dataset4.0", type, space, H5P_DEFAULT); + /* Don't write any data */ + ret = H5Dclose(dset); + ret = H5Tclose(type); + + /* write out an empty compound dataset */ + type = H5Tcreate(H5T_COMPOUND,sizeof(empty_struct)); + H5Tinsert(type, "a", HOFFSET(empty_struct, a),H5T_NATIVE_INT); + H5Tinsert(type, "b", HOFFSET(empty_struct, b),H5T_NATIVE_FLOAT); + H5Tinsert(type, "c", HOFFSET(empty_struct, c),H5T_NATIVE_CHAR); + dset = H5Dcreate(file, "Dataset5.0", type, space, H5P_DEFAULT); + /* Don't write any data */ + ret = H5Dclose(dset); + ret = H5Tclose(type); + + ret = H5Sclose(space); + + ret = H5Fclose(file); +} + +int main(void) +{ + test_group(); + test_attribute(); + test_softlink(); + test_dataset(); + test_hardlink(); + test_compound_dt(); + test_all(); + test_loop(); + + test_dataset2(); + test_compound_dt2(); + test_loop2(); + test_many(); + + test_str(); + test_str2(); + + test_enum(); + + test_objref(); + test_datareg(); + + test_nestcomp(); + + test_opaque(); + + test_bitfields(); + + test_vldatatypes(); + test_vldatatypes2(); + test_vldatatypes3(); + test_vldatatypes4(); + + test_array1(); + test_array2(); + test_array3(); + test_array4(); + test_array5(); + test_array6(); + test_array7(); + + test_empty(); + + return 0; +} diff --git a/tools/h5dump/testh5dump.sh b/tools/h5dump/testh5dump.sh new file mode 100755 index 0000000..05dfb09 --- /dev/null +++ b/tools/h5dump/testh5dump.sh @@ -0,0 +1,197 @@ +#! /bin/sh +# +# Copyright (C) 1998-2001 National Center for Supercomputing Applications +# All rights reserved. +# +# Tests for the h5dump tool + +DUMPER=h5dump # The tool name +DUMPER_BIN=`pwd`/$DUMPER # The path of the tool binary + +CMP='cmp -s' +DIFF='diff -c' + +nerrors=0 +verbose=yes + +# The build (current) directory might be different than the source directory. +if test -z "$srcdir"; then + srcdir=. +fi + +test -d ../testfiles || mkdir ../testfiles + +# 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 output and the expected output. The +# expected output is given as the first argument to this function and +# the actual output file is calculated by replacing the `.ddl' with +# `.out'. The actual output is not removed if $HDF5_NOCLEANUP has a +# non-zero value. +# +TOOLTEST() { + expect="$srcdir/../testfiles/$1" + actual="../testfiles/`basename $1 .ddl`.out" + shift + + # Run test. + TESTING $DUMPER $@ + + ( + echo "#############################" + echo "Expected output for '$DUMPER $@'" + echo "#############################" + cd $srcdir/../testfiles + $RUNSERIAL $DUMPER_BIN "$@" + ) >$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 |