hdf5/test/titerate.c
Quincey Koziol 56e63bdeea [svn-r13287] Description:
Add H5Aget_info_by_idx & H5Aget_name_by_idx routines, along with
refactoring underlying indices code to handle those sort of queries.

	Simplify the link callback routines a bit.

	Minor other cleanups.

Tested on:
	Mac OS X/32 10.4.8 (amazon)
	FreeBSD/32 6.2 (duty)
2007-02-13 09:50:48 -05:00

959 lines
32 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***********************************************************
*
* 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,
RET_CHANGE2
} 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(HDstrcmp(*(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;
static int count2 = 0;
HDstrcpy(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);
case RET_CHANGE2:
count2++;
return(count2 > 10 ? 1 : 0);
default:
printf("invalid iteration command");
return(-1);
} /* end switch */
} /* end giter_cb() */
/****************************************************************
**
** test_iter_group(): Test group iteration functionality
**
****************************************************************/
static void test_iter_group(hid_t fapl, hbool_t new_format)
{
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 *lnames[NDATASETS + 2];/* Names of the links 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, fapl);
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 */
lnames[i] = HDstrdup(name);
CHECK(lnames[i], NULL, "strdup");
ret = H5Dclose(dataset);
CHECK(ret, FAIL, "H5Dclose");
} /* end for */
/* Create a group and named datatype under root group for testing
* H5Gget_objtype_by_idx.
*/
grp = H5Gcreate(file, "grp", (size_t)0);
CHECK(ret, FAIL, "H5Gcreate");
lnames[NDATASETS] = HDstrdup("grp");
CHECK(lnames[NDATASETS], NULL, "strdup");
ret = H5Tcommit(file, "dtype", datatype);
CHECK(ret, FAIL, "H5Tcommit");
lnames[NDATASETS + 1] = HDstrdup("dtype");
CHECK(lnames[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(lnames, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp);
/* Iterate through the datasets in the root group in various ways */
file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl);
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, (size_t)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");
} /* end for */
H5E_BEGIN_TRY {
ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)(NDATASETS+3), dataset_name, (size_t)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, (size_t)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, (size_t)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 "2" is returned */
i++;
/* Verify that the index is the correct value */
VERIFY(idx, i, "H5Giterate");
if(idx > (NDATASETS + 2))
TestErrPrintf("Group iteration function walked too far!\n");
/* Verify that the correct name is retrieved */
if(HDstrcmp(info.name, lnames[idx - 1]) != 0)
TestErrPrintf("Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n", (idx - 1), lnames[idx - 1]);
} /* end while */
VERIFY(ret, -1, "H5Giterate");
if(i != (NDATASETS + 2))
TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__);
/* Test all objects in group, when callback changes return value */
/* This also tests the "restarting" ability, because the index changes */
info.command = new_format ? RET_CHANGE2 : 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");
if(idx > (NDATASETS + 2))
TestErrPrintf("Group iteration function walked too far!\n");
/* Verify that the correct name is retrieved */
if(HDstrcmp(info.name, lnames[idx - 1]) != 0)
TestErrPrintf("Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n", (idx - 1), lnames[idx - 1]);
} /* end while */
VERIFY(ret, -1, "H5Giterate");
if(i != 42 || idx != 52)
TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__);
ret = H5Fclose(file);
CHECK(ret, FAIL, "H5Fclose");
/* Free the dataset names */
for(i = 0; i< (NDATASETS + 2); i++)
HDfree(lnames[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;
static int count2 = 0;
HDstrcpy(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);
case RET_CHANGE2:
count2++;
return(count2 > 10 ? 1 : 0);
default:
printf("invalid iteration command");
return(-1);
} /* end switch */
} /* end aiter_cb() */
/****************************************************************
**
** test_iter_attr(): Test attribute iteration functionality
**
****************************************************************/
static void test_iter_attr(hid_t fapl, hbool_t new_format)
{
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, fapl);
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, fapl);
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 "2" 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("%u: Attribute iteration function didn't return 'two' correctly!\n", __LINE__);
} /* end while */
VERIFY(ret, -1, "H5Aiterate");
if(i != 50 || idx != 50)
TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__);
/* Test all attributes on dataset, when callback changes return value */
/* This also tests the "restarting" ability, because the index changes */
info.command = new_format ? RET_CHANGE2 : 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");
} /* end while */
VERIFY(ret, -1, "H5Aiterate");
if(i != 40 || idx != 50)
TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__);
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(HDstrcmp((const char *)s1, (const char *)s2));
} /* end iter_strcmp2() */
/****************************************************************
**
** 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;
H5G_stat_t statbuf;
herr_t ret; /* Generic return value */
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(hid_t fapl)
{
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;
HDmemset(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, fapl);
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 */
HDstrcpy(names[i].name, gname);
names[i].type = H5G_GROUP;
/* Create a group */
group = H5Gcreate(file, gname, (size_t)0);
CHECK(group, FAIL, "H5Gcreate");
/* Close a group */
ret = H5Gclose(group);
CHECK(ret, FAIL, "H5Gclose");
} /* end for */
/* 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 */
HDstrcpy(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 */
HDstrcpy(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 */
HDqsort(names, (size_t)(ITER_NGROUPS + 2), sizeof(iter_info), iter_strcmp2);
/* Iterate through the file to see members of the root group */
curr_name = &names[0];
ret = H5Giterate(file, "/", NULL, giter_cb2, curr_name);
CHECK(ret, FAIL, "H5Giterate");
for(i = 1; i < 100; ) {
curr_name = &names[i];
ret = H5Giterate(file, "/", &i, giter_cb2, curr_name);
CHECK(ret, FAIL, "H5Giterate");
} /* 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(hid_t fapl)
{
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, fapl);
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");
} /* end for */
/* Create a group and named datatype under root group for testing
* H5Gget_objtype_by_idx.
*/
grp = H5Gcreate(file, "grp", (size_t)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, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp);
/* Iterate through the datasets in the root group in various ways */
file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl);
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, (size_t)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", (size_t)7))
VERIFY(obj_type, H5G_DATASET, "H5Gget_objname_by_idx");
} /* end for */
H5E_BEGIN_TRY {
ret = (herr_t)H5Gget_objname_by_idx(root_group, (hsize_t)(NDATASETS+3), dataset_name, (size_t)NAMELEN);
} H5E_END_TRY;
VERIFY(ret, FAIL, "H5Gget_objname_by_idx");
/* Sort the dataset names */
HDqsort(obj_names, (size_t)(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");
} /* end for */
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++) {
HDfree(dnames[i]);
HDfree(obj_names[i]);
} /* end for */
} /* test_grp_memb_funcs() */
/****************************************************************
**
** test_links(): Test soft and hard link iteration
**
****************************************************************/
static void test_links(hid_t fapl)
{
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, fapl);
CHECK(file, FAIL, "H5Fcreate");
/* create groups */
gid = H5Gcreate(file, "/g1", (size_t)0);
CHECK(gid, FAIL, "H5Gcreate");
gid1 = H5Gcreate(file, "/g1/g1.1", (size_t)0);
CHECK(gid1, FAIL, "H5Gcreate");
/* create soft and hard links to the group "/g1". */
ret = H5Glink (gid, H5L_TYPE_SOFT, "something", "softlink");
CHECK(ret, FAIL, "H5Glink");
ret = H5Glink (gid, H5L_TYPE_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, (size_t)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)
{
hid_t fapl, fapl2; /* File access property lists */
hbool_t new_format; /* Whether to use the new format or not */
herr_t ret; /* Generic return value */
/* Output message about test being performed */
MESSAGE(5, ("Testing Iteration Operations\n"));
/* Get the default FAPL */
fapl = H5Pcreate(H5P_FILE_ACCESS);
CHECK(fapl, FAIL, "H5Pcreate");
/* Copy the file access property list */
fapl2 = H5Pcopy(fapl);
CHECK(fapl2, FAIL, "H5Pcopy");
/* Set the "use the latest version of the format" flag for creating objects in the file */
ret = H5Pset_latest_format(fapl2, TRUE);
CHECK(ret, FAIL, "H5Pset_latest_format");
/* These next tests use the same file */
for(new_format = FALSE; new_format <= TRUE; new_format++) {
test_iter_group(new_format ? fapl2 : fapl, new_format); /* Test group iteration */
test_iter_group_large(new_format ? fapl2 : fapl); /* Test group iteration for large # of objects */
test_iter_attr(new_format ? fapl2 : fapl, new_format); /* Test attribute iteration */
test_grp_memb_funcs(new_format ? fapl2 : fapl); /* Test group member information functions */
test_links(new_format ? fapl2 : fapl); /* Test soft and hard link iteration */
} /* end for */
/* Close FAPLs */
ret = H5Pclose(fapl);
CHECK(ret, FAIL, "H5Pclose");
ret = H5Pclose(fapl2);
CHECK(ret, FAIL, "H5Pclose");
} /* 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);
}