/* This is part of the netCDF package. Copyright 2005 University Corporation for Atmospheric Research/Unidata See COPYRIGHT file for conditions of use. Test HDF5 file code. These are not intended to be exhaustive tests, but they use HDF5 the same way that netCDF-4 does, so if these tests don't work, than netCDF-4 won't work either. This program deals with HDF5 compound types. $Id: tst_h_compounds.c,v 1.25 2010/06/01 15:34:51 ed Exp $ */ #include "h5_err_macros.h" #include <hdf5.h> #define FILE_NAME "tst_h_compounds.h5" #define DIM1_LEN 3 #define OSMONDS "TheOsmonds" #define WHO "TheWho" #define BOOZE_VAR "Alcohol_Consumed" #define BEER_OR_WINE "Beer_or_Wine" #define LIQUOR "The_Hard_Stuff" #define COMPOUND_NAME "Booze_Index" #define ARRAY_LEN 5 #define STR_LEN 255 int main() { hid_t fileid, osmonds_grpid, who_grpid, spaceid, typeid; hid_t datasetid, datasetid1, typeid1; hsize_t dims[1]; struct s1 { int i1, i2; } data[DIM1_LEN]; struct s2 { int i1[ARRAY_LEN], i2; } data2[DIM1_LEN]; char *dummy; int i, j; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct s2), DIM1_LEN))) ERR; memcpy((void *)data2, (void *)dummy, sizeof(struct s2) * DIM1_LEN); free(dummy); if (!(dummy = calloc(sizeof(struct s1), DIM1_LEN))) ERR; memcpy((void *)data2, (void *)dummy, sizeof(struct s1) * DIM1_LEN); free(dummy); for (i=0; i<DIM1_LEN; i++) { data[i].i1 = 99; data[i].i2 = -99; data2[i].i2 = -99; for (j=0; j<ARRAY_LEN; j++) data2[i].i1[j] = 99; } printf("\n*** Checking HDF5 compound types.\n"); printf("*** Checking simple HDF5 compound types..."); { /* Open file and create group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gcreate(fileid, OSMONDS, 0)) < 0) ERR; /* Create a simple compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid, BEER_OR_WINE, HOFFSET(struct s1, i1), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, LIQUOR, HOFFSET(struct s1, i2), H5T_NATIVE_INT) < 0) ERR; if (H5Tcommit(osmonds_grpid, COMPOUND_NAME, typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(osmonds_grpid, BOOZE_VAR, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gopen(fileid, OSMONDS)) < 0) ERR; if ((datasetid = H5Dopen1(osmonds_grpid, BOOZE_VAR)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Tget_nmembers(typeid) != 2) ERR; /* This doesn't work because all I have is a reference to the type! if (H5Iget_name(typeid, type_name, STR_LEN) < 0) ERR; if (strcmp(type_name, COMPOUND_NAME)) ERR;*/ /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound types and groups..."); { /* Open file and create two group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gcreate(fileid, OSMONDS, 0)) < 0) ERR; if ((who_grpid = H5Gcreate(fileid, WHO, 0)) < 0) ERR; /* Create a simple compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid, BEER_OR_WINE, HOFFSET(struct s1, i1), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, LIQUOR, HOFFSET(struct s1, i2), H5T_NATIVE_INT) < 0) ERR; if (H5Tcommit(osmonds_grpid, COMPOUND_NAME, typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type in the same group. */ if ((datasetid = H5Dcreate(osmonds_grpid, BOOZE_VAR, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0) ERR; /* Create a dataset of this compound type in a different group. */ if ((datasetid1 = H5Dcreate(who_grpid, BOOZE_VAR, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid1, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Dclose(datasetid1) < 0 || H5Tclose(typeid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Gclose(who_grpid) < 0 || H5Fclose(fileid) < 0) ERR; { hsize_t num_obj; int i, obj_type; char name[STR_LEN + 1]; htri_t equal; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gopen(fileid, OSMONDS)) < 0) ERR; if (H5Gget_num_objs(osmonds_grpid, &num_obj) < 0) ERR; for (i=0; i<num_obj; i++) { if (H5Gget_objname_by_idx(osmonds_grpid, i, name, STR_LEN+1) < 0) ERR; if ((obj_type = H5Gget_objtype_by_idx(osmonds_grpid, i)) < 0) ERR; switch(obj_type) { case H5G_DATASET: if ((datasetid = H5Dopen1(osmonds_grpid, name)) < 0) ERR; break; case H5G_TYPE: if ((typeid = H5Topen(osmonds_grpid, name)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Tget_nmembers(typeid) != 2) ERR; if (strcmp(name, COMPOUND_NAME)) ERR; break; default: ERR; } } /* Open the other dataset, and learn about its type. */ if ((who_grpid = H5Gopen(fileid, WHO)) < 0) ERR; if ((datasetid1 = H5Dopen1(who_grpid, BOOZE_VAR)) < 0) ERR; if ((typeid1 = H5Dget_type(datasetid1)) < 0) ERR; if ((equal = H5Tequal(typeid, typeid1)) < 0) ERR; if (!equal) ERR; } /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Dclose(datasetid1) < 0 || H5Tclose(typeid) < 0 || H5Tclose(typeid1) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Gclose(who_grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound type which contains an array..."); { hsize_t array_dims[] = {ARRAY_LEN}; hid_t array_typeid; /* Open file and create group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gcreate(fileid, OSMONDS, 0)) < 0) ERR; /* Create an array type. */ if ((array_typeid = H5Tarray_create(H5T_NATIVE_INT, 1, array_dims, NULL)) < 0) ERR; /* Create a compound type containing an array. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct s2))) < 0) ERR; if (H5Tinsert(typeid, BEER_OR_WINE, HOFFSET(struct s2, i1), array_typeid) < 0) ERR; if (H5Tinsert(typeid, LIQUOR, HOFFSET(struct s2, i2), H5T_NATIVE_INT) < 0) ERR; if (H5Tcommit(osmonds_grpid, COMPOUND_NAME, typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(osmonds_grpid, BOOZE_VAR, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data2) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(array_typeid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((osmonds_grpid = H5Gopen(fileid, OSMONDS)) < 0) ERR; if ((datasetid = H5Dopen1(osmonds_grpid, BOOZE_VAR)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Tget_nmembers(typeid) != 2) ERR; /* This doesn't work because all I have is a reference to the type! if (H5Iget_name(typeid, type_name, STR_LEN) < 0) ERR; if (strcmp(type_name, COMPOUND_NAME)) ERR;*/ /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(osmonds_grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound type 6 different types..."); { #define DAY "day" #define ELEV "elev" #define COUNT "count" #define RELHUM "relhum" #define TIME "time" #define OBS_T "obs_t" #define OBS_VAR "obs_var" #define DIM6_LEN 3 hid_t fileid, grpid, spaceid, typeid, native_typeid; hid_t datasetid, mem_type; hsize_t dims[1]; typedef struct obs_t { char day ; short elev; int count; float relhum; double time; } obs_t ; obs_t obsdata[DIM6_LEN]; obs_t obsdata_in[DIM6_LEN], obsdata2_in[DIM6_LEN]; char file_in[STR_LEN * 2]; char *dummy; size_t size_in; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct obs_t), DIM6_LEN))) ERR; memcpy((void *)obsdata, (void *)dummy, sizeof(struct obs_t) * DIM6_LEN); free(dummy); /* Initialize data. */ for (i = 0; i < DIM6_LEN; i++) { obsdata[i].day = 15 * i + 1; obsdata[i].elev = 2 * i + 1; obsdata[i].count = 2 * i + 1; obsdata[i].relhum = 2.0 * i + 1; obsdata[i].time = 2.0 * i + 1; } /* Open file and create group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type containing some different types. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct obs_t))) < 0) ERR; if (H5Tinsert(typeid, DAY, HOFFSET(struct obs_t, day), H5T_NATIVE_CHAR) < 0) ERR; if (H5Tinsert(typeid, ELEV, HOFFSET(struct obs_t, elev), H5T_NATIVE_SHORT) < 0) ERR; if (H5Tinsert(typeid, COUNT, HOFFSET(struct obs_t, count), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, RELHUM, HOFFSET(struct obs_t, relhum), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, TIME, HOFFSET(struct obs_t, time), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, OBS_T, typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM6_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(grpid, OBS_VAR, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, obsdata) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((datasetid = H5Dopen1(grpid, OBS_VAR)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if ((size_in = H5Tget_size(typeid)) == 0) ERR; if (size_in != sizeof(struct obs_t)) ERR; if ((native_typeid = H5Tget_native_type(typeid, H5T_DIR_DEFAULT)) < 0) ERR; if ((size_in = H5Tget_size(native_typeid)) == 0) ERR; if (size_in != sizeof(struct obs_t)) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Tget_nmembers(typeid) != 5) ERR; /* Read all data. */ if (H5Dread(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, obsdata_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM6_LEN; i++) { if (obsdata[i].day != obsdata_in[i].day || obsdata[i].elev != obsdata_in[i].elev || obsdata[i].count != obsdata_in[i].count || obsdata[i].relhum != obsdata_in[i].relhum || obsdata[i].time != obsdata_in[i].time) { ERR; return 1; } } /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the reference copy of this file and read it. */ #define REF_FILE_NAME "ref_tst_h_compounds.h5" if (getenv("srcdir")) { strcpy(file_in, getenv("srcdir")); strcat(file_in, "/"); strcat(file_in, REF_FILE_NAME); } else strcpy(file_in, REF_FILE_NAME); if ((fileid = H5Fopen(file_in, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((datasetid = H5Dopen1(grpid, OBS_VAR)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if ((mem_type = H5Tget_native_type(typeid, H5T_DIR_DEFAULT)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Tget_nmembers(typeid) != 5) ERR; /* Read all data. */ if (H5Dread(datasetid, mem_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, obsdata2_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM6_LEN; i++) { if (obsdata[i].day != obsdata2_in[i].day || obsdata[i].elev != obsdata2_in[i].elev || obsdata[i].count != obsdata2_in[i].count || obsdata[i].relhum != obsdata2_in[i].relhum || obsdata[i].time != obsdata2_in[i].time) { ERR; return 1; } } /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound variable which contains a compound type..."); { #define DATASET_NAME "Enterprise" /* This struct will be embeddeded in another. */ struct s1 { int i1; int i2; }; /* StarFleet Human Resources Department has data records for all * employees. */ struct hr_rec { int starfleet_id; struct s1 svc_rec; char name[STR_LEN + 1]; float max_temp, min_temp; /* temperature range */ double percent_transporter_errosion; }; struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN]; hid_t fileid, grpid, typeid_inner, typeid, spaceid, array1_tid, datasetid; hsize_t dims[1]; char *dummy; int i; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct hr_rec), DIM1_LEN))) ERR; memcpy((void *)hr_data_out, (void *)dummy, sizeof(struct hr_rec) * DIM1_LEN); free(dummy); /* Create some phony data. */ for (i = 0; i < DIM1_LEN; i++) { hr_data_out[i].starfleet_id = i; hr_data_out[i].svc_rec.i1 = 95; hr_data_out[i].svc_rec.i2 = 90; if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR; hr_data_out[i].max_temp = 99.99; hr_data_out[i].min_temp = -9.99; hr_data_out[i].percent_transporter_errosion = .1; } /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid_inner = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid_inner, "i1", HOFFSET(struct s1, i1), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid_inner, "i2", HOFFSET(struct s1, i2), H5T_NATIVE_INT) < 0) ERR; /* Create a compound type containing a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct hr_rec))) < 0) ERR; if (H5Tinsert(typeid, "starfleet_id", HOFFSET(struct hr_rec, starfleet_id), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, "svc_rec", HOFFSET(struct hr_rec, svc_rec), typeid_inner) < 0) ERR; if ((array1_tid = H5Tcopy(H5T_C_S1)) < 0) ERR; if (H5Tset_size(array1_tid, STR_LEN + 1) < 0) ERR; if (H5Tinsert(typeid, "name", HOFFSET(struct hr_rec, name), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "max_temp", HOFFSET(struct hr_rec, max_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "min_temp", HOFFSET(struct hr_rec, min_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "percent_transporter_errosion", HOFFSET(struct hr_rec, percent_transporter_errosion), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, "hr_rec", typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(grpid, DATASET_NAME, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_out) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(array1_tid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(typeid_inner) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((datasetid = H5Dopen1(grpid, DATASET_NAME)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Dread(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM1_LEN; i++) if (hr_data_out[i].starfleet_id != hr_data_in[i].starfleet_id || hr_data_out[i].svc_rec.i1 != hr_data_in[i].svc_rec.i1 || hr_data_out[i].svc_rec.i2 != hr_data_in[i].svc_rec.i2 || strcmp(hr_data_out[i].name, hr_data_in[i].name) || hr_data_out[i].max_temp != hr_data_in[i].max_temp || hr_data_out[i].min_temp != hr_data_in[i].min_temp || hr_data_out[i].percent_transporter_errosion != hr_data_in[i].percent_transporter_errosion) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 variable which contains a compound type with different string handling..."); { #define DATASET_NAME "Enterprise" /* This struct will be embeddeded in another. */ struct s1 { int i1; int i2; }; /* StarFleet Human Resources Department has data records for all * employees. */ struct hr_rec { int starfleet_id; struct s1 svc_rec; char name[STR_LEN + 1]; float max_temp, min_temp; /* temperature range */ double percent_transporter_errosion; }; struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN]; hid_t fileid, grpid, typeid_inner, typeid, spaceid, array1_tid, datasetid, str_tid; hsize_t dims[1]; int i; /* Create some phony data. */ for (i = 0; i < DIM1_LEN; i++) { hr_data_out[i].starfleet_id = i; hr_data_out[i].svc_rec.i1 = 95; hr_data_out[i].svc_rec.i2 = 90; if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR; hr_data_out[i].max_temp = 99.99; hr_data_out[i].min_temp = -9.99; hr_data_out[i].percent_transporter_errosion = .1; } /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid_inner = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid_inner, "i1", HOFFSET(struct s1, i1), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid_inner, "i2", HOFFSET(struct s1, i2), H5T_NATIVE_INT) < 0) ERR; /* Create a compound type containing a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct hr_rec))) < 0) ERR; if (H5Tinsert(typeid, "starfleet_id", HOFFSET(struct hr_rec, starfleet_id), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, "svc_rec", HOFFSET(struct hr_rec, svc_rec), typeid_inner) < 0) ERR; dims[0] = STR_LEN + 1; if ((str_tid = H5Tcopy(H5T_C_S1)) < 0) ERR; if (H5Tset_strpad(str_tid, H5T_STR_NULLTERM) < 0) ERR; if ((array1_tid = H5Tarray_create2(str_tid, 1, dims)) < 0) ERR; if (H5Tinsert(typeid, "name", HOFFSET(struct hr_rec, name), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "max_temp", HOFFSET(struct hr_rec, max_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "min_temp", HOFFSET(struct hr_rec, min_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "percent_transporter_errosion", HOFFSET(struct hr_rec, percent_transporter_errosion), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, "hr_rec", typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(grpid, DATASET_NAME, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_out) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(array1_tid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(typeid_inner) < 0 || H5Tclose(str_tid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((datasetid = H5Dopen1(grpid, DATASET_NAME)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Dread(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM1_LEN; i++) if (hr_data_out[i].starfleet_id != hr_data_in[i].starfleet_id || hr_data_out[i].svc_rec.i1 != hr_data_in[i].svc_rec.i1 || hr_data_out[i].svc_rec.i2 != hr_data_in[i].svc_rec.i2 || strcmp(hr_data_out[i].name, hr_data_in[i].name) || hr_data_out[i].max_temp != hr_data_in[i].max_temp || hr_data_out[i].min_temp != hr_data_in[i].min_temp || hr_data_out[i].percent_transporter_errosion != hr_data_in[i].percent_transporter_errosion) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound attribute which contains a compound type..."); { #define ATT_NAME1 "Space_Station_Regula_One" /* This struct will be embeddeded in another. */ struct s1 { int i1; int i2; }; /* StarFleet Human Resources Department has data records for all * employees. */ struct hr_rec { int starfleet_id; struct s1 svc_rec; char name[STR_LEN + 1]; float max_temp, min_temp; /* temperature range */ double percent_transporter_errosion; }; struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN]; hid_t fileid, grpid, typeid_inner, typeid, spaceid, array1_tid, attid, native_typeid; hsize_t dims[1]; int i; /* Create some phony data. */ for (i = 0; i < DIM1_LEN; i++) { hr_data_out[i].starfleet_id = i; hr_data_out[i].svc_rec.i1 = 95; hr_data_out[i].svc_rec.i2 = 90; if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR; hr_data_out[i].max_temp = 99.99; hr_data_out[i].min_temp = -9.99; hr_data_out[i].percent_transporter_errosion = .1; } /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid_inner = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid_inner, "i1", HOFFSET(struct s1, i1), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid_inner, "i2", HOFFSET(struct s1, i2), H5T_NATIVE_INT) < 0) ERR; /* Create a compound type containing a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct hr_rec))) < 0) ERR; if (H5Tinsert(typeid, "starfleet_id", HOFFSET(struct hr_rec, starfleet_id), H5T_NATIVE_INT) < 0) ERR; if (H5Tinsert(typeid, "svc_rec", HOFFSET(struct hr_rec, svc_rec), typeid_inner) < 0) ERR; if ((array1_tid = H5Tcopy(H5T_C_S1)) < 0) ERR; if (H5Tset_size(array1_tid, STR_LEN + 1) < 0) ERR; if (H5Tinsert(typeid, "name", HOFFSET(struct hr_rec, name), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "max_temp", HOFFSET(struct hr_rec, max_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "min_temp", HOFFSET(struct hr_rec, min_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid, "percent_transporter_errosion", HOFFSET(struct hr_rec, percent_transporter_errosion), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, "hr_rec", typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create an attribute of this compound type. */ if ((attid = H5Acreate2(grpid, ATT_NAME1, typeid, spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; /* Write some data to the attribute. */ if (H5Awrite(attid, typeid, hr_data_out) < 0) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(typeid_inner) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((attid = H5Aopen_by_name(grpid, ".", ATT_NAME1, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((typeid = H5Aget_type(attid)) < 0) ERR; if ((native_typeid = H5Tget_native_type(typeid, H5T_DIR_DEFAULT)) < 0) ERR; if (H5Aread(attid, native_typeid, hr_data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM1_LEN; i++) if (hr_data_out[i].starfleet_id != hr_data_in[i].starfleet_id || hr_data_out[i].svc_rec.i1 != hr_data_in[i].svc_rec.i1 || hr_data_out[i].svc_rec.i2 != hr_data_in[i].svc_rec.i2 || strcmp(hr_data_out[i].name, hr_data_in[i].name) || hr_data_out[i].max_temp != hr_data_in[i].max_temp || hr_data_out[i].min_temp != hr_data_in[i].min_temp || hr_data_out[i].percent_transporter_errosion != hr_data_in[i].percent_transporter_errosion) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 variable of compound type which contains a string..."); { #define DATASET_NAME "Enterprise" struct hr_rec { char name[STR_LEN + 1]; float max_temp; }; struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN]; hid_t fileid, grpid, typeid, spaceid, array1_tid, datasetid, str_tid; hsize_t dims[1] = {STR_LEN + 1}; int i; /* Create some phony data. */ for (i = 0; i < DIM1_LEN; i++) { if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR; hr_data_out[i].max_temp = 99.99; } /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct hr_rec))) < 0) ERR; /* printf("sizeof(struct hr_rec)=%d dims[0]=%d\n", sizeof(struct hr_rec), dims[0]);*/ if ((str_tid = H5Tcopy(H5T_C_S1)) < 0) ERR; if (H5Tset_strpad(str_tid, H5T_STR_NULLTERM) < 0) ERR; if ((array1_tid = H5Tarray_create2(str_tid, 1, dims)) < 0) ERR; /* printf("sizeof(struct hr_rec)=%d HOFFSET(struct hr_rec, name) = %d HOFFSET(struct hr_rec, max_temp) = %d\n", sizeof(struct hr_rec), HOFFSET(struct hr_rec, name), HOFFSET(struct hr_rec, max_temp));*/ if (H5Tinsert(typeid, "name", HOFFSET(struct hr_rec, name), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "max_temp", HOFFSET(struct hr_rec, max_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tcommit(grpid, "hr_rec", typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create a dataset of this compound type. */ if ((datasetid = H5Dcreate(grpid, DATASET_NAME, typeid, spaceid, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Dwrite(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_out) < 0) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(array1_tid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(str_tid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((datasetid = H5Dopen1(grpid, DATASET_NAME)) < 0) ERR; if ((typeid = H5Dget_type(datasetid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Dread(datasetid, typeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, hr_data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM1_LEN; i++) if (strcmp(hr_data_out[i].name, hr_data_in[i].name) || hr_data_out[i].max_temp != hr_data_in[i].max_temp) ERR; /* Release all resources. */ if (H5Dclose(datasetid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound attribute which contains an array of char..."); { #define DIM2_LEN 1 #define ATT_NAME "HR_Records" struct hr_rec { char name[STR_LEN + 1]; float max_temp; }; struct hr_rec hr_data_out[DIM2_LEN], hr_data_in[DIM2_LEN]; hid_t fileid, grpid, typeid, spaceid, array1_tid, attid, str_tid; hsize_t dims[1] = {STR_LEN + 1}; char *dummy; int i; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct hr_rec), DIM2_LEN))) ERR; memcpy((void *)hr_data_out, (void *)dummy, sizeof(struct hr_rec) * DIM2_LEN); free(dummy); /* Create some phony data. */ for (i = 0; i < DIM2_LEN; i++) { if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR; hr_data_out[i].max_temp = 99.99; } /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct hr_rec))) < 0) ERR; if ((str_tid = H5Tcopy(H5T_C_S1)) < 0) ERR; if (H5Tset_strpad(str_tid, H5T_STR_NULLTERM) < 0) ERR; if ((array1_tid = H5Tarray_create2(str_tid, 1, dims)) < 0) ERR; /* printf("sizeof(struct hr_rec)=%d HOFFSET(struct hr_rec, name) = %d HOFFSET(struct hr_rec, max_temp) = %d\n", sizeof(struct hr_rec), HOFFSET(struct hr_rec, name), HOFFSET(struct hr_rec, max_temp));*/ if (H5Tinsert(typeid, "Name", HOFFSET(struct hr_rec, name), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "Max_Temp", HOFFSET(struct hr_rec, max_temp), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tcommit(grpid, "SF_HR_Record", typeid) < 0) ERR; /* Create a space. */ dims[0] = DIM2_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create an attribute of this compound type. */ if ((attid = H5Acreate2(grpid, ATT_NAME, typeid, spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Awrite(attid, typeid, hr_data_out) < 0) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(array1_tid) < 0 || H5Tclose(typeid) < 0 || H5Tclose(str_tid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((attid = H5Aopen_by_name(grpid, ".", ATT_NAME, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((typeid = H5Aget_type(attid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Aread(attid, typeid, hr_data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DIM2_LEN; i++) if (strcmp(hr_data_out[i].name, hr_data_in[i].name) || hr_data_out[i].max_temp != hr_data_in[i].max_temp) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking HDF5 compound attribute which contains an array of unsigned byte..."); { #define DISC_DIM1_LEN 2 #define DISC_ATT_NAME "Discovery" struct s1 { unsigned char x[STR_LEN + 1]; float y; }; struct s1 data_out[DISC_DIM1_LEN], data_in[DISC_DIM1_LEN]; hid_t fileid, grpid, typeid, spaceid, array1_tid, attid; hid_t fcpl_id, fapl_id; hsize_t dims[1] = {STR_LEN + 1}; int i, j; /* Create some data. */ for (i = 0; i < DISC_DIM1_LEN; i++) { for (j = 0; j < STR_LEN + 1; j++) data_out[i].x[j] = 4; data_out[i].y = 99.99; } /* Set latest_format in access propertly list and * H5P_CRT_ORDER_TRACKED in the creation property list. This * turns on HDF5 creation ordering. */ if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR; if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR; if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR; if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR; if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; /* Open file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create a compound type. */ if ((typeid = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if ((array1_tid = H5Tarray_create2(H5T_NATIVE_UCHAR, 1, dims)) < 0) ERR; if (H5Tinsert(typeid, "x", HOFFSET(struct s1, x), array1_tid) < 0) ERR; if (H5Tinsert(typeid, "y", HOFFSET(struct s1, y), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tcommit(grpid, "c", typeid) < 0) ERR; /* Create a space. */ dims[0] = DISC_DIM1_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create an attribute of this compound type. */ if ((attid = H5Acreate2(grpid, DISC_ATT_NAME, typeid, spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; /* Write some data. */ if (H5Awrite(attid, typeid, data_out) < 0) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(array1_tid) < 0 || H5Tclose(typeid) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and read it. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((attid = H5Aopen_by_name(grpid, ".", DISC_ATT_NAME, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((typeid = H5Aget_type(attid)) < 0) ERR; if (H5Tget_class(typeid) != H5T_COMPOUND) ERR; if (H5Aread(attid, typeid, data_in) < 0) ERR; /* Check the data. */ for (i = 0; i < DISC_DIM1_LEN; i++) { for (j = 0; j < STR_LEN + 1; j++) if (data_in[i].x[j] != data_out[i].x[j]) ERR_RET; if (data_in[i].y != data_out[i].y) ERR; } /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking simple read of HDF5 compound attribute which contains a simple compound type..."); { #define DIM_CMP_LEN 1 #define ATT_CMP_NAME1 "The_Nutmeg_of_Consolation" #define NUM_TYPES 2 #define INNER_TYPE_NAME "s1" #define OUTER_TYPE_NAME "d" /* This struct will be embeddeded in another. */ struct s1 { float x; double y; }; struct s2 { struct s1 s1; }; struct s2 data_out[DIM_CMP_LEN], data_in[DIM_CMP_LEN]; hid_t fileid, grpid, typeid_inner, typeid_outer, spaceid, attid; hid_t att_typeid, att_native_typeid; hsize_t dims[1]; hid_t fapl_id, fcpl_id; char *dummy; int i; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct s2), DIM_CMP_LEN))) ERR; memcpy((void *)data_out, (void *)dummy, sizeof(struct s2) * DIM_CMP_LEN); free(dummy); /* Create some phony data. */ for (i = 0; i < DIM_CMP_LEN; i++) { data_out[i].s1.x = 1.0; data_out[i].s1.y = -2.0; } /* Create file access and create property lists. */ if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR; if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR; if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR; if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; /* Create file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create the inner compound type. */ if ((typeid_inner = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid_inner, "x", HOFFSET(struct s1, x), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid_inner, "y", HOFFSET(struct s1, y), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, INNER_TYPE_NAME, typeid_inner) < 0) ERR; /* Create a compound type containing a compound type. */ if ((typeid_outer = H5Tcreate(H5T_COMPOUND, sizeof(struct s2))) < 0) ERR; if (H5Tinsert(typeid_outer, INNER_TYPE_NAME, HOFFSET(struct s2, s1), typeid_inner) < 0) ERR; if (H5Tcommit(grpid, OUTER_TYPE_NAME, typeid_outer) < 0) ERR; /* Create a space. */ dims[0] = DIM_CMP_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create an attribute of this compound type. */ if ((attid = H5Acreate2(grpid, ATT_CMP_NAME1, typeid_outer, spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; /* Write some data to the attribute. */ if (H5Awrite(attid, typeid_outer, data_out) < 0) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid_outer) < 0 || H5Tclose(typeid_inner) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and get the type of the attribute. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((attid = H5Aopen_by_name(grpid, ".", ATT_CMP_NAME1, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((att_typeid = H5Aget_type(attid)) < 0) ERR; if ((att_native_typeid = H5Tget_native_type(att_typeid, H5T_DIR_DEFAULT)) < 0) ERR; /* Check the data. */ if (H5Aread(attid, att_native_typeid, data_in) < 0) ERR; for (i = 0; i < DIM_CMP_LEN; i++) if (data_out[i].s1.x != data_in[i].s1.x || data_out[i].s1.y != data_in[i].s1.y) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(att_typeid) < 0 || H5Tclose(att_native_typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; printf("*** Checking simple read of HDF5 compound attribute which contains a simple compound type..."); { #define DIM_CMP_LEN 1 #define ATT_CMP_NAME1 "The_Nutmeg_of_Consolation" #define NUM_TYPES 2 #define INNER_TYPE_NAME "s1" #define OUTER_TYPE_NAME "d" /* This struct will be embeddeded in another. */ struct s1 { float x; double y; }; struct s2 { struct s1 s1; }; struct s2 data_out[DIM_CMP_LEN], data_in[DIM_CMP_LEN]; hid_t fileid, grpid, typeid_inner, typeid_outer, spaceid, attid; hid_t att_typeid, att_native_typeid; hsize_t dims[1]; hid_t fapl_id, fcpl_id; int i; /* REALLY initialize the data (even the gaps in the structs). This * is only needed to pass valgrind. */ if (!(dummy = calloc(sizeof(struct s2), DIM_CMP_LEN))) ERR; memcpy((void *)data_out, (void *)dummy, sizeof(struct s2) * DIM_CMP_LEN); free(dummy); /* Create some phony data. */ for (i = 0; i < DIM_CMP_LEN; i++) { data_out[i].s1.x = 1.0; data_out[i].s1.y = -2.0; } /* Create file access and create property lists. */ if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR; if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR; if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR; if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED)) < 0) ERR; /* Create file and get root group. */ if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; /* Create the inner compound type. */ if ((typeid_inner = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) ERR; if (H5Tinsert(typeid_inner, "x", HOFFSET(struct s1, x), H5T_NATIVE_FLOAT) < 0) ERR; if (H5Tinsert(typeid_inner, "y", HOFFSET(struct s1, y), H5T_NATIVE_DOUBLE) < 0) ERR; if (H5Tcommit(grpid, INNER_TYPE_NAME, typeid_inner) < 0) ERR; /* Create a compound type containing a compound type. */ if ((typeid_outer = H5Tcreate(H5T_COMPOUND, sizeof(struct s2))) < 0) ERR; if (H5Tinsert(typeid_outer, INNER_TYPE_NAME, HOFFSET(struct s2, s1), typeid_inner) < 0) ERR; if (H5Tcommit(grpid, OUTER_TYPE_NAME, typeid_outer) < 0) ERR; /* Create a space. */ dims[0] = DIM_CMP_LEN; if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR; /* Create an attribute of this compound type. */ if ((attid = H5Acreate2(grpid, ATT_CMP_NAME1, typeid_outer, spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; /* Write some data to the attribute. */ if (H5Awrite(attid, typeid_outer, data_out) < 0) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(typeid_outer) < 0 || H5Tclose(typeid_inner) < 0 || H5Sclose(spaceid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; /* Now open the file and get the type of the attribute. */ if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; if ((grpid = H5Gopen(fileid, "/")) < 0) ERR; if ((attid = H5Aopen_by_name(grpid, ".", ATT_CMP_NAME1, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR; if ((att_typeid = H5Aget_type(attid)) < 0) ERR; if ((att_native_typeid = H5Tget_native_type(att_typeid, H5T_DIR_DEFAULT)) < 0) ERR; /* Check the data. */ if (H5Aread(attid, att_native_typeid, data_in) < 0) ERR; for (i = 0; i < DIM_CMP_LEN; i++) if (data_out[i].s1.x != data_in[i].s1.x || data_out[i].s1.y != data_in[i].s1.y) ERR; /* Release all resources. */ if (H5Aclose(attid) < 0 || H5Tclose(att_typeid) < 0 || H5Tclose(att_native_typeid) < 0 || H5Gclose(grpid) < 0 || H5Fclose(fileid) < 0) ERR; } SUMMARIZE_ERR; FINAL_RESULTS; }