/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*********************************************************** * * Test program: titerate * * Test the Group & Attribute functionality * *************************************************************/ #include "testhdf5.h" #include "hdf5.h" #define DATAFILE "titerate.h5" /* Number of datasets for group iteration test */ #define NDATASETS 50 /* Number of attributes for attribute iteration test */ #define NATTR 50 /* Number of groups for second group iteration test */ #define ITER_NGROUPS 150 /* General maximum length of names used */ #define NAMELEN 80 /* 1-D dataset with fixed dimensions */ #define SPACE1_NAME "Space1" #define SPACE1_RANK 1 #define SPACE1_DIM1 4 typedef enum { RET_ZERO, RET_TWO, RET_CHANGE } iter_enum; /* Custom group iteration callback data */ typedef struct { char name[NAMELEN]; /* The name of the object */ int type; /* The type of the object */ iter_enum command; /* The type of return value */ } iter_info; /* Local functions */ int iter_strcmp(const void *s1, const void *s2); int iter_strcmp2(const void *s1, const void *s2); herr_t giter_cb(hid_t group, const char *name, void *op_data); herr_t giter_cb2(hid_t group, const char *name, void *op_data); herr_t aiter_cb(hid_t loc_id, const char *name, void *op_data); /**************************************************************** ** ** iter_strcmp(): String comparison routine for qsort ** ****************************************************************/ int iter_strcmp(const void *s1, const void *s2) { return(strcmp(*(const char * const *)s1,*(const char * const *)s2)); } /**************************************************************** ** ** giter_cb(): Custom group iteration callback routine. ** ****************************************************************/ herr_t giter_cb(hid_t UNUSED group, const char *name, void *op_data) { iter_info *info=(iter_info *)op_data; static int count=0; strcpy(info->name,name); switch(info->command) { case RET_ZERO: return(0); case RET_TWO: return(2); case RET_CHANGE: count++; return(count>10 ? 1: 0); default: printf("invalid iteration command"); return(-1); } /* end switch */ } /**************************************************************** ** ** test_iter_group(): Test group iteration functionality ** ****************************************************************/ static void test_iter_group(void) { hid_t file; /* File ID */ hid_t dataset; /* Dataset ID */ hid_t datatype; /* Common datatype ID */ hid_t filespace; /* Common dataspace ID */ hid_t root_group,grp; /* Root group ID */ int i; /* counting variable */ int idx; /* Index in the group */ char name[NAMELEN]; /* temporary name buffer */ char *dnames[NDATASETS];/* Names of the datasets created */ char dataset_name[NAMELEN]; /* dataset name */ iter_info info; /* Custom iteration information */ hsize_t num_membs; /* Number of group members */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Group Iteration Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); /* Test iterating over empty group */ info.command=RET_ZERO; idx=0; ret=H5Giterate(file,"/",&idx,giter_cb,&info); VERIFY(ret, SUCCEED, "H5Giterate"); datatype = H5Tcopy(H5T_NATIVE_INT); CHECK(datatype, FAIL, "H5Tcopy"); filespace=H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); for(i=0; i< NDATASETS; i++) { sprintf(name,"Dataset %d",i); dataset = H5Dcreate(file, name, datatype, filespace, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); /* Keep a copy of the dataset names around for later */ dnames[i]=HDstrdup(name); CHECK(dnames[i], NULL, "strdup"); ret=H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); } /* Create a group and named datatype under root group for testing * H5Gget_objtype_by_idx. */ grp = H5Gcreate(file, "grp", 0); CHECK(ret, FAIL, "H5Gcreate"); ret = H5Tcommit(file, "dtype", datatype); CHECK(ret, FAIL, "H5Tcommit"); /* Close everything up */ ret=H5Tclose(datatype); CHECK(ret, FAIL, "H5Tclose"); ret=H5Gclose(grp); CHECK(ret, FAIL, "H5Gclose"); ret=H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Sort the dataset names */ HDqsort(dnames,NDATASETS,sizeof(char *),iter_strcmp); /* Iterate through the datasets in the root group in various ways */ file=H5Fopen(DATAFILE, H5F_ACC_RDONLY, H5P_DEFAULT); CHECK(file, FAIL, "H5Fopen"); /* These two functions, H5Gget_num_objs and H5Gget_objname_by_idx, actually * iterate through B-tree for group members in internal library design. */ { root_group = H5Gopen(file, "/"); CHECK(root_group, FAIL, "H5Gopen"); ret = H5Gget_num_objs(root_group, &num_membs); CHECK(ret, FAIL, "H5Gget_num_objs"); VERIFY(num_membs,NDATASETS+2,"H5Gget_num_objs"); for(i=0; i< (int)num_membs; i++) { H5G_obj_t obj_type; /* Type of object in file */ ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)i, dataset_name, NAMELEN); CHECK(ret, FAIL, "H5Gget_objname_by_idx"); obj_type = H5Gget_objtype_by_idx(root_group, (hsize_t)i); CHECK(obj_type, H5G_UNKNOWN, "H5Gget_objtype_by_idx"); } H5E_BEGIN_TRY { ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)(NDATASETS+3), dataset_name, NAMELEN); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Gget_objname_by_idx"); ret = H5Gclose(root_group); CHECK(ret, FAIL, "H5Gclose"); } /* These two functions, H5Gget_num_objs and H5Gget_objname_by_idx, actually * iterate through B-tree for group members in internal library design. * (Same as test above, but with the file ID instead of opening the root group) */ { ret = H5Gget_num_objs(file, &num_membs); CHECK(ret, FAIL, "H5Gget_num_objs"); VERIFY(num_membs,NDATASETS+2,"H5Gget_num_objs"); for(i=0; i< (int)num_membs; i++) { H5G_obj_t obj_type; /* Type of object in file */ ret = (herr_t)H5Gget_objname_by_idx(file, (hsize_t)i, dataset_name, NAMELEN); CHECK(ret, FAIL, "H5Gget_objname_by_idx"); obj_type = H5Gget_objtype_by_idx(file, (hsize_t)i); CHECK(obj_type, H5G_UNKNOWN, "H5Gget_objtype_by_idx"); } H5E_BEGIN_TRY { ret = (herr_t)H5Gget_objname_by_idx(file, (hsize_t)(NDATASETS+3), dataset_name, NAMELEN); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Gget_objname_by_idx"); } /* Test invalid indices for starting iteration */ info.command=RET_ZERO; idx=-1; H5E_BEGIN_TRY { ret=H5Giterate(file,"/",&idx,giter_cb,&info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Giterate"); /* Test skipping exactly as many entries as in the group */ idx=NDATASETS+2; H5E_BEGIN_TRY { ret=H5Giterate(file,"/",&idx,giter_cb,&info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Giterate"); /* Test skipping more entries than are in the group */ idx=NDATASETS+3; H5E_BEGIN_TRY { ret=H5Giterate(file,"/",&idx,giter_cb,&info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Giterate"); /* Test all objects in group, when callback always returns 0 */ info.command=RET_ZERO; idx=0; if((ret=H5Giterate(file,"/",&idx,giter_cb,&info))>0) TestErrPrintf("Group iteration function didn't return zero correctly!\n"); /* Test all objects in group, when callback always returns 1 */ /* This also tests the "restarting" ability, because the index changes */ info.command=RET_TWO; idx=i=0; while((ret=H5Giterate(file,"/",&idx,giter_cb,&info))>0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret,2,"H5Giterate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx,i,"H5Giterate"); /* Verify that the correct name is retrieved */ if(idx<=NDATASETS) { if(HDstrcmp(info.name,dnames[idx-1])!=0) TestErrPrintf("Group iteration function didn't return one correctly for dataset #%d!\n",idx); } /* end if */ else if(idx==(NDATASETS+1)) { if(HDstrcmp(info.name,"dtype")!=0) TestErrPrintf("Group iteration function didn't return one correctly for group!\n"); } /* end if */ else if(idx==(NDATASETS+2)) { if(HDstrcmp(info.name,"grp")!=0) TestErrPrintf("Group iteration function didn't return one correctly for group!\n"); } /* end if */ else TestErrPrintf("Group iteration function walked too far!\n"); } VERIFY(ret,-1,"H5Giterate"); if(i!=(NDATASETS+2)) TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); /* Test all objects in group, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ info.command=RET_CHANGE; idx=i=0; while((ret=H5Giterate(file,"/",&idx,giter_cb,&info))>=0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret,1,"H5Giterate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx,i+10,"H5Giterate"); /* Verify that the correct name is retrieved */ if(idx<=NDATASETS) { if(HDstrcmp(info.name,dnames[idx-1])!=0) TestErrPrintf("Group iteration function didn't return one correctly for dataset #%d!\n",idx); } /* end if */ else if(idx==(NDATASETS+1)) { if(HDstrcmp(info.name,"dtype")!=0) TestErrPrintf("Group iteration function didn't return one correctly for group!\n"); } /* end if */ else if(idx==(NDATASETS+2)) { if(HDstrcmp(info.name,"grp")!=0) TestErrPrintf("Group iteration function didn't return one correctly for group!\n"); } /* end if */ else TestErrPrintf("Group iteration function walked too far!\n"); } VERIFY(ret,-1,"H5Giterate"); if(i!=42 || idx!=52) TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Free the dataset names */ for(i=0; i< NDATASETS; i++) HDfree(dnames[i]); } /* test_iter_group() */ /**************************************************************** ** ** aiter_cb(): Custom group iteration callback routine. ** ****************************************************************/ herr_t aiter_cb(hid_t UNUSED group, const char *name, void *op_data) { iter_info *info=(iter_info *)op_data; static int count=0; strcpy(info->name,name); switch(info->command) { case RET_ZERO: return(0); case RET_TWO: return(2); case RET_CHANGE: count++; return(count>10 ? 1: 0); default: printf("invalid iteration command"); return(-1); } /* end switch */ } /**************************************************************** ** ** test_iter_attr(): Test attribute iteration functionality ** ****************************************************************/ static void test_iter_attr(void) { hid_t file; /* File ID */ hid_t dataset; /* Common Dataset ID */ hid_t filespace; /* Common dataspace ID */ hid_t attribute; /* Attribute ID */ int i; /* counting variable */ unsigned idx; /* Index in the attribute list */ char name[NAMELEN]; /* temporary name buffer */ char *anames[NATTR]; /* Names of the attributes created */ iter_info info; /* Custom iteration information */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Attribute Iteration Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); filespace=H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); dataset = H5Dcreate(file, "Dataset", H5T_NATIVE_INT, filespace, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); for(i=0; i< NATTR; i++) { sprintf(name,"Attribute %d",i); attribute = H5Acreate(dataset, name, H5T_NATIVE_INT, filespace, H5P_DEFAULT); CHECK(attribute, FAIL, "H5Acreate"); /* Keep a copy of the attribute names around for later */ anames[i]=HDstrdup(name); CHECK(anames[i], NULL, "strdup"); ret=H5Aclose(attribute); CHECK(ret, FAIL, "H5Aclose"); } /* Close everything up */ ret=H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret=H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Iterate through the attributes on the dataset in various ways */ file=H5Fopen(DATAFILE, H5F_ACC_RDONLY, H5P_DEFAULT); CHECK(file, FAIL, "H5Fopen"); dataset=H5Dopen(file, "Dataset"); CHECK(dataset, FAIL, "H5Dopen"); /* Test invalid indices for starting iteration */ info.command=RET_ZERO; /* Test skipping exactly as many attributes as there are */ idx=NATTR; H5E_BEGIN_TRY { ret=H5Aiterate(dataset,&idx,aiter_cb,&info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Aiterate"); /* Test skipping more attributes than there are */ idx=NATTR+1; H5E_BEGIN_TRY { ret=H5Aiterate(dataset,&idx,aiter_cb,&info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Aiterate"); /* Test all attributes on dataset, when callback always returns 0 */ info.command=RET_ZERO; idx=0; if((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) TestErrPrintf("Attribute iteration function didn't return zero correctly!\n"); /* Test all attributes on dataset, when callback always returns 1 */ /* This also tests the "restarting" ability, because the index changes */ info.command=RET_TWO; idx=i=0; while((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret,2,"H5Aiterate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx,(unsigned)i,"H5Aiterate"); /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name,anames[idx-1])!=0) TestErrPrintf("Attribute iteration function didn't return one correctly!\n"); } VERIFY(ret,-1,"H5Aiterate"); if(i!=50 || idx!=50) TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); /* Test all attributes on dataset, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ info.command=RET_CHANGE; idx=i=0; while((ret=H5Aiterate(dataset,&idx,aiter_cb,&info))>0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret,1,"H5Aiterate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx,(unsigned)i+10,"H5Aiterate"); /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name,anames[idx-1])!=0) TestErrPrintf("Attribute iteration function didn't return changing correctly!\n"); } VERIFY(ret,-1,"H5Aiterate"); if(i!=40 || idx!=50) TestErrPrintf("Group iteration function didn't perform multiple iterations correctly!\n"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); ret=H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Free the attribute names */ for(i=0; i< NATTR; i++) HDfree(anames[i]); } /* test_iter_attr() */ /**************************************************************** ** ** iter_strcmp2(): String comparison routine for qsort ** ****************************************************************/ int iter_strcmp2(const void *s1, const void *s2) { return(strcmp((const char *)s1,(const char *)s2)); } /**************************************************************** ** ** giter_cb2(): Custom group iteration callback routine. ** ****************************************************************/ herr_t giter_cb2(hid_t loc_id, const char *name, void *opdata) { const iter_info *test_info=(const iter_info *)opdata; herr_t ret; /* Generic return value */ H5G_stat_t statbuf; if(HDstrcmp(name,test_info->name)) { TestErrPrintf("name=%s, test_info=%s\n",name,test_info->name); return(-1); } /* end if */ /* * Get type of the object and check it. */ ret=H5Gget_objinfo(loc_id, name, FALSE, &statbuf); CHECK(ret, FAIL, "H5Gget_objinfo"); if(test_info->type!=statbuf.type) { TestErrPrintf("test_info->type=%d, statbuf.type=%d\n",test_info->type,statbuf.type); return(-1); } /* end if */ return(1); } /* giter_cb2() */ /**************************************************************** ** ** test_iter_group_large(): Test group iteration functionality ** for groups with large #'s of objects ** ****************************************************************/ static void test_iter_group_large(void) { hid_t file; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t group; /* Group ID */ hid_t sid; /* Dataspace ID */ hid_t tid; /* Datatype ID */ hsize_t dims[] = {SPACE1_DIM1}; herr_t ret; /* Generic return value */ char gname[20]; /* Temporary group name */ iter_info names[ITER_NGROUPS+2]; /* Names of objects in the root group */ iter_info *curr_name; /* Pointer to the current name in the root group */ int i; /* Compound datatype */ typedef struct s1_t { unsigned int a; unsigned int b; float c; } s1_t; memset(names, 0, sizeof names); /* Output message about test being performed */ MESSAGE(5, ("Testing Large Group Iteration Functionality\n")); /* Create file */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); /* Create dataspace for datasets */ sid = H5Screate_simple(SPACE1_RANK, dims, NULL); CHECK(sid, FAIL, "H5Screate_simple"); /* Create a bunch of groups */ for (i=0; i<ITER_NGROUPS; i++) { sprintf(gname, "Group_%d", i); /* Add the name to the list of objects in the root group */ strcpy(names[i].name,gname); names[i].type=H5G_GROUP; /* Create a group */ group=H5Gcreate(file,gname,0); CHECK(group, FAIL, "H5Gcreate"); /* Close a group */ ret = H5Gclose(group); CHECK(ret, FAIL, "H5Gclose"); } /* Create a dataset */ dataset=H5Dcreate(file,"Dataset1",H5T_STD_U32LE,sid,H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); /* Add the name to the list of objects in the root group */ strcpy(names[ITER_NGROUPS].name,"Dataset1"); names[ITER_NGROUPS].type=H5G_DATASET; /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Close Dataspace */ ret = H5Sclose(sid); CHECK(ret, FAIL, "H5Sclose"); /* Create a datatype */ tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); CHECK(tid, FAIL, "H5Tcreate"); /* Insert fields */ ret=H5Tinsert (tid, "a", HOFFSET(s1_t,a), H5T_NATIVE_INT); CHECK(ret, FAIL, "H5Tinsert"); ret=H5Tinsert (tid, "b", HOFFSET(s1_t,b), H5T_NATIVE_INT); CHECK(ret, FAIL, "H5Tinsert"); ret=H5Tinsert (tid, "c", HOFFSET(s1_t,c), H5T_NATIVE_FLOAT); CHECK(ret, FAIL, "H5Tinsert"); /* Save datatype for later */ ret=H5Tcommit (file, "Datatype1", tid); CHECK(ret, FAIL, "H5Tcommit"); /* Add the name to the list of objects in the root group */ strcpy(names[ITER_NGROUPS+1].name,"Datatype1"); names[ITER_NGROUPS+1].type=H5G_TYPE; /* Close datatype */ ret = H5Tclose(tid); CHECK(ret, FAIL, "H5Tclose"); /* Need to sort the names in the root group, cause that's what the library does */ qsort(names,ITER_NGROUPS+2,sizeof(iter_info),iter_strcmp2); /* Iterate through the file to see members of the root group */ curr_name=&names[0]; H5Giterate(file, "/", NULL, giter_cb2, curr_name); for (i=1; i<100; ) { curr_name=&names[i]; H5Giterate(file, "/", &i, giter_cb2, curr_name); } /* end for */ /* Close file */ ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); } /* test_iterate_group_large() */ /**************************************************************** ** ** test_grp_memb_funcs(): Test group member information ** functionality ** ****************************************************************/ static void test_grp_memb_funcs(void) { hid_t file; /* File ID */ hid_t dataset; /* Dataset ID */ hid_t datatype; /* Common datatype ID */ hid_t filespace; /* Common dataspace ID */ hid_t root_group,grp; /* Root group ID */ int i; /* counting variable */ char name[NAMELEN]; /* temporary name buffer */ char *dnames[NDATASETS+2];/* Names of the datasets created */ char *obj_names[NDATASETS+2];/* Names of the objects in group */ char dataset_name[NAMELEN]; /* dataset name */ ssize_t name_len; /* Length of object's name */ hsize_t num_membs; /* Number of group members */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Group Member Information Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); datatype = H5Tcopy(H5T_NATIVE_INT); CHECK(datatype, FAIL, "H5Tcopy"); filespace=H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); for(i=0; i< NDATASETS; i++) { sprintf(name,"Dataset %d",i); dataset = H5Dcreate(file, name, datatype, filespace, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate"); /* Keep a copy of the dataset names around for later */ dnames[i]=HDstrdup(name); CHECK(dnames[i], NULL, "strdup"); ret=H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); } /* Create a group and named datatype under root group for testing * H5Gget_objtype_by_idx. */ grp = H5Gcreate(file, "grp", 0); CHECK(ret, FAIL, "H5Gcreate"); dnames[NDATASETS]=HDstrdup("grp"); CHECK(dnames[NDATASETS], NULL, "strdup"); ret = H5Tcommit(file, "dtype", datatype); CHECK(ret, FAIL, "H5Tcommit"); dnames[NDATASETS+1]=HDstrdup("dtype"); CHECK(dnames[NDATASETS], NULL, "strdup"); /* Close everything up */ ret=H5Tclose(datatype); CHECK(ret, FAIL, "H5Tclose"); ret=H5Gclose(grp); CHECK(ret, FAIL, "H5Gclose"); ret=H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Sort the dataset names */ HDqsort(dnames,NDATASETS+2,sizeof(char *),iter_strcmp); /* Iterate through the datasets in the root group in various ways */ file=H5Fopen(DATAFILE, H5F_ACC_RDONLY, H5P_DEFAULT); CHECK(file, FAIL, "H5Fopen"); /* These two functions, H5Gget_num_objs and H5Gget_objname_by_idx, actually * iterate through B-tree for group members in internal library design. */ root_group = H5Gopen(file, "/"); CHECK(root_group, FAIL, "H5Gopen"); ret = H5Gget_num_objs(root_group, &num_membs); CHECK(ret, FAIL, "H5Gget_num_objs"); VERIFY(num_membs,NDATASETS+2,"H5Gget_num_objs"); for(i=0; i< (int)num_membs; i++) { H5G_obj_t obj_type; /* Type of object in file */ /* Test with NULL for name, to query length */ name_len = H5Gget_objname_by_idx(root_group, (hsize_t)i, NULL, NAMELEN); CHECK(name_len, FAIL, "H5Gget_objname_by_idx"); ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)i, dataset_name, (size_t)(name_len+1)); CHECK(ret, FAIL, "H5Gget_objname_by_idx"); /* Double-check that the length is the same */ VERIFY(ret, name_len, "H5Gget_objname_by_idx"); /* Keep a copy of the dataset names around for later */ obj_names[i]=HDstrdup(dataset_name); CHECK(obj_names[i], NULL, "strdup"); obj_type = H5Gget_objtype_by_idx(root_group, (hsize_t)i); CHECK(obj_type, H5G_UNKNOWN, "H5Gget_objtype_by_idx"); if(!HDstrcmp(dataset_name, "grp")) VERIFY(obj_type, H5G_GROUP, "H5Gget_objname_by_idx"); if(!HDstrcmp(dataset_name, "dtype")) VERIFY(obj_type, H5G_TYPE, "H5Gget_objname_by_idx"); if(!HDstrncmp(dataset_name, "Dataset", 7)) VERIFY(obj_type, H5G_DATASET, "H5Gget_objname_by_idx"); } H5E_BEGIN_TRY { ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)(NDATASETS+3), dataset_name, NAMELEN); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Gget_objname_by_idx"); /* Sort the dataset names */ qsort(obj_names,NDATASETS+2,sizeof(char *),iter_strcmp); /* Compare object names */ for(i=0; i< (int)num_membs; i++) { ret = HDstrcmp(dnames[i], obj_names[i]); VERIFY(ret, 0, "HDstrcmp"); } ret = H5Gclose(root_group); CHECK(ret, FAIL, "H5Gclose"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Free the dataset names */ for(i=0; i< NDATASETS+2; i++) { free(dnames[i]); free(obj_names[i]); } } /* test_grp_memb_funcs() */ /**************************************************************** ** ** test_links(): Test soft and hard link iteration ** ****************************************************************/ static void test_links(void) { hid_t file; /* File ID */ char obj_name[NAMELEN]; /* Names of the object in group */ ssize_t name_len; /* Length of object's name */ herr_t ret; /* Generic return value */ hid_t gid, gid1; hsize_t i; H5G_obj_t obj_type; /* Type of object */ hsize_t nobjs; /* Number of objects */ /* Output message about test being performed */ MESSAGE(5, ("Testing Soft and Hard Link Iteration Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); /* create groups */ gid = H5Gcreate (file, "/g1", 0); CHECK(gid, FAIL, "H5Gcreate"); gid1 = H5Gcreate (file, "/g1/g1.1", 0); CHECK(gid1, FAIL, "H5Gcreate"); /* create soft and hard links to the group "/g1". */ ret = H5Glink (gid, H5G_LINK_SOFT, "something", "softlink"); CHECK(ret, FAIL, "H5Glink"); ret = H5Glink (gid, H5G_LINK_HARD, "/g1", "hardlink"); CHECK(ret, FAIL, "H5Glink"); ret = H5Gget_num_objs(gid, &nobjs); CHECK(ret, FAIL, "H5Gget_num_objs"); VERIFY(nobjs,3,"H5Gget_num_objs"); /* Test these two functions, H5Gget_num_objs and H5Gget_objname_by_idx */ for(i=0; i<nobjs; i++) { /* Get object name */ name_len = H5Gget_objname_by_idx(gid, i, obj_name, NAMELEN); CHECK(name_len, FAIL, "H5Gget_objname_by_idx"); obj_type = H5Gget_objtype_by_idx(gid, i); CHECK(obj_type, H5G_UNKNOWN, "H5Gget_objtype_by_idx"); if(!HDstrcmp(obj_name, "g1.1")) VERIFY(obj_type, H5G_GROUP, "H5Gget_objname_by_idx"); else if(!HDstrcmp(obj_name, "hardlink")) VERIFY(obj_type, H5G_GROUP, "H5Gget_objname_by_idx"); else if(!HDstrcmp(obj_name, "softlink")) VERIFY(obj_type, H5G_LINK, "H5Gget_objname_by_idx"); else CHECK(0, 0, "unknown object name"); } ret=H5Gclose(gid); CHECK(ret, FAIL, "H5Gclose"); ret=H5Gclose(gid1); CHECK(ret, FAIL, "H5Gclose"); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); } /* test_links() */ /**************************************************************** ** ** test_iterate(): Main iteration testing routine. ** ****************************************************************/ void test_iterate(void) { /* Output message about test being performed */ MESSAGE(5, ("Testing Iteration Operations\n")); /* These next tests use the same file */ test_iter_group(); /* Test group iteration */ test_iter_group_large(); /* Test group iteration for large # of objects */ test_iter_attr(); /* Test attribute iteration */ test_grp_memb_funcs(); /* Test group member information functions */ test_links(); /* Test soft and hard link iteration */ } /* test_iterate() */ /*------------------------------------------------------------------------- * Function: cleanup_iterate * * Purpose: Cleanup temporary test files * * Return: none * * Programmer: Quincey Koziol * April 5, 2000 * * Modifications: * *------------------------------------------------------------------------- */ void cleanup_iterate(void) { remove(DATAFILE); }