int main (void) { hid_t file, filetype, memtype, strtype, space, dset; /* Handles */ herr_t status; hsize_t dims[1] = {DIM0}; sensor_t wdata[DIM0], /* Write buffer */ *rdata; /* Read buffer */ int ndims, i; /* * Initialize data. */ wdata[0].serial_no = 1153; wdata[0].location = "Exterior (static)"; wdata[0].temperature = 53.23; wdata[0].pressure = 24.57; wdata[1].serial_no = 1184; wdata[1].location = "Intake"; wdata[1].temperature = 55.12; wdata[1].pressure = 22.95; wdata[2].serial_no = 1027; wdata[2].location = "Intake manifold"; wdata[2].temperature = 103.55; wdata[2].pressure = 31.23; wdata[3].serial_no = 1313; wdata[3].location = "Exhaust manifold"; wdata[3].temperature = 1252.89; wdata[3].pressure = 84.11; /* * Create a new file using the default properties. */ file = H5Fcreate (FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); /* * Create variable-length string datatype. */ strtype = H5Tcopy (H5T_C_S1); status = H5Tset_size (strtype, H5T_VARIABLE); /* * Create the compound datatype for memory. */ memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t)); status = H5Tinsert (memtype, "Serial number", HOFFSET (sensor_t, serial_no), H5T_NATIVE_INT); status = H5Tinsert (memtype, "Location", HOFFSET (sensor_t, location), strtype); status = H5Tinsert (memtype, "Temperature (F)", HOFFSET (sensor_t, temperature), H5T_NATIVE_DOUBLE); status = H5Tinsert (memtype, "Pressure (inHg)", HOFFSET (sensor_t, pressure), H5T_NATIVE_DOUBLE); /* * Create the compound datatype for the file. Because the standard * types we are using for the file may have different sizes than * the corresponding native types, we must manually calculate the * offset of each member. */ filetype = H5Tcreate (H5T_COMPOUND, 8 + sizeof (hvl_t) + 8 + 8); status = H5Tinsert (filetype, "Serial number", 0, H5T_STD_I64BE); status = H5Tinsert (filetype, "Location", 8, strtype); status = H5Tinsert (filetype, "Temperature (F)", 8 + sizeof (hvl_t), H5T_IEEE_F64BE); status = H5Tinsert (filetype, "Pressure (inHg)", 8 + sizeof (hvl_t) + 8, H5T_IEEE_F64BE); /* * Create dataspace. Setting maximum size to NULL sets the maximum * size to be the current size. */ space = H5Screate_simple (1, dims, NULL); /* * Create the dataset and write the compound data to it. */ dset = H5Dcreate (file, DATASET, filetype, space, H5P_DEFAULT); status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); /* * Close and release resources. */ status = H5Dclose (dset); status = H5Sclose (space); status = H5Tclose (filetype); status = H5Fclose (file); /* * Now we begin the read section of this example. Here we assume * the dataset has the same name and rank, but can have any size. * Therefore we must allocate a new array to read in data using * malloc(). For simplicity, we do not rebuild memtype. */ /* * Open file and dataset. */ file = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT); dset = H5Dopen (file, DATASET); /* * Get dataspace and allocate memory for read buffer. */ space = H5Dget_space (dset); ndims = H5Sget_simple_extent_dims (space, dims, NULL); rdata = (sensor_t *) malloc (dims[0] * sizeof (sensor_t)); /* * Read the data. */ status = H5Dread (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); /* * Output the data to the screen. */ for (i=0; i<dims[0]; i++) { printf ("%s[%d]:\n", DATASET, i); printf ("Serial number : %d\n", rdata[i].serial_no); printf ("Location : %s\n", rdata[i].location); printf ("Temperature (F) : %f\n", rdata[i].temperature); printf ("Pressure (inHg) : %f\n\n", rdata[i].pressure); } /* * Close and release resources. H5Dvlen_reclaim will automatically * traverse the structure and free any vlen data (strings in this * case). */ status = H5Dvlen_reclaim (memtype, space, H5P_DEFAULT, rdata); free (rdata); status = H5Dclose (dset); status = H5Sclose (space); status = H5Tclose (memtype); status = H5Tclose (strtype); status = H5Fclose (file); return 0; }
herr_t HDF5AttrIterate( hid_t hH5ObjID, const char *pszAttrName, void *pDS ) { hid_t hAttrID; hid_t hAttrTypeID; hid_t hAttrNativeType; hid_t hAttrSpace; char *szData = NULL; hsize_t nSize[64]; unsigned int nAttrElmts; hsize_t nAttrSize; hsize_t i; void *buf = NULL; unsigned int nAttrDims; char **papszTokens; HDF5Dataset *poDS; CPLString osKey; char *szValue = NULL; poDS = (HDF5Dataset *) pDS; // Convert "/" into "_" for the path component const char* pszPath = poDS->poH5CurrentObject->pszUnderscorePath; if(pszPath != NULL && strlen(pszPath) > 0) { papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS ); for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i ) { if( i != 0) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy( papszTokens ); } // Convert whitespaces into "_" for the attribute name component papszTokens = CSLTokenizeString2( pszAttrName, " ", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i ) { if(!osKey.empty()) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy( papszTokens ); hAttrID = H5Aopen_name( hH5ObjID, pszAttrName ); hAttrTypeID = H5Aget_type( hAttrID ); hAttrNativeType = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT ); hAttrSpace = H5Aget_space( hAttrID ); nAttrDims = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL ); nAttrElmts = 1; for( i=0; i < nAttrDims; i++ ) { nAttrElmts *= (int) nSize[i]; } if( H5Tget_class( hAttrNativeType ) == H5T_STRING ) { if ( H5Tis_variable_str(hAttrNativeType) ) { char** papszStrings; papszStrings = (char**) CPLMalloc( nAttrElmts * sizeof(char*) ); // Read the values H5Aread( hAttrID, hAttrNativeType, papszStrings ); // Concatenate all values as one string (separated by a space) CPLString osVal = papszStrings[0]; for( i=1; i < nAttrElmts; i++ ) { osVal += " "; osVal += papszStrings[i]; } szValue = (char*) CPLMalloc(osVal.length() + 1); strcpy( szValue, osVal.c_str() ); H5Dvlen_reclaim( hAttrNativeType, hAttrSpace, H5P_DEFAULT, papszStrings ); CPLFree( papszStrings ); } else { nAttrSize = H5Aget_storage_size( hAttrID ); szValue = (char*) CPLMalloc((size_t) (nAttrSize+1)); H5Aread( hAttrID, hAttrNativeType, szValue ); szValue[nAttrSize] = '\0'; } } else { if( nAttrElmts > 0 ) { buf = (void *) CPLMalloc( nAttrElmts* H5Tget_size( hAttrNativeType )); szData = (char*) CPLMalloc( 8192 ); szValue = (char*) CPLMalloc( MAX_METADATA_LEN ); szData[0] = '\0'; szValue[0] ='\0'; H5Aread( hAttrID, hAttrNativeType, buf ); } if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) || H5Tequal( H5T_NATIVE_SCHAR, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%c ", ((char *) buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_UCHAR, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%c", ((char *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_SHORT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%d ", ((short *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ud ", ((unsigned short *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_INT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%d ", ((int *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_UINT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ud ", ((unsigned int *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_LONG, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ld ", ((long *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_ULONG, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ld ", ((unsigned long *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_FLOAT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { CPLsprintf( szData, "%.8g ", ((float *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { CPLsprintf( szData, "%.15g ", ((double *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } CPLFree( buf ); } H5Sclose(hAttrSpace); H5Tclose(hAttrNativeType); H5Tclose(hAttrTypeID); H5Aclose( hAttrID ); poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, osKey, szValue); CPLFree( szData ); CPLFree( szValue ); return 0; }
/*------------------------------------------------------------------------- * Function: diff_datasetid * * Purpose: check for comparable datasets and read into a compatible * memory type * * Return: Number of differences found * * Programmer: Pedro Vicente, [email protected] * * Date: May 9, 2003 * * Modifications: * * * October 2006: Read by hyperslabs for big datasets. * * A threshold of H5TOOLS_MALLOCSIZE (128 MB) is the limit upon which I/O hyperslab is done * i.e., if the memory needed to read a dataset is greater than this limit, * then hyperslab I/O is done instead of one operation I/O * For each dataset, the memory needed is calculated according to * * memory needed = number of elements * size of each element * * if the memory needed is lower than H5TOOLS_MALLOCSIZE, then the following operations * are done * * H5Dread( input_dataset1 ) * H5Dread( input_dataset2 ) * * with all elements in the datasets selected. If the memory needed is greater than * H5TOOLS_MALLOCSIZE, then the following operations are done instead: * * a strip mine is defined for each dimension k (a strip mine is defined as a * hyperslab whose size is memory manageable) according to the formula * * (1) strip_mine_size[k ] = MIN(dimension[k ], H5TOOLS_BUFSIZE / size of memory type) * * where H5TOOLS_BUFSIZE is a constant currently defined as 1MB. This formula assures * that for small datasets (small relative to the H5TOOLS_BUFSIZE constant), the strip * mine size k is simply defined as its dimension k, but for larger datasets the * hyperslab size is still memory manageable. * a cycle is done until the number of elements in the dataset is reached. In each * iteration, two parameters are defined for the function H5Sselect_hyperslab, * the start and size of each hyperslab, according to * * (2) hyperslab_size [k] = MIN(dimension[k] - hyperslab_offset[k], strip_mine_size [k]) * * where hyperslab_offset [k] is initially set to zero, and later incremented in * hyperslab_size[k] offsets. The reason for the operation * * dimension[k] - hyperslab_offset[k] * * in (2) is that, when using the strip mine size, it assures that the "remaining" part * of the dataset that does not fill an entire strip mine is processed. * *------------------------------------------------------------------------- */ hsize_t diff_datasetid( hid_t did1, hid_t did2, const char *obj1_name, const char *obj2_name, diff_opt_t *options) { hid_t sid1=-1; hid_t sid2=-1; hid_t f_tid1=-1; hid_t f_tid2=-1; hid_t m_tid1=-1; hid_t m_tid2=-1; size_t m_size1; size_t m_size2; H5T_sign_t sign1; H5T_sign_t sign2; int rank1; int rank2; hsize_t nelmts1; hsize_t nelmts2; hsize_t dims1[H5S_MAX_RANK]; hsize_t dims2[H5S_MAX_RANK]; hsize_t maxdim1[H5S_MAX_RANK]; hsize_t maxdim2[H5S_MAX_RANK]; const char *name1=NULL; /* relative names */ const char *name2=NULL; hsize_t storage_size1; hsize_t storage_size2; hsize_t nfound=0; /* number of differences found */ int can_compare=1; /* do diff or not */ void *buf1=NULL; void *buf2=NULL; void *sm_buf1=NULL; void *sm_buf2=NULL; size_t need; /* bytes needed for malloc */ int i; /* Get the dataspace handle */ if ( (sid1 = H5Dget_space(did1)) < 0 ) goto error; /* Get rank */ if ( (rank1 = H5Sget_simple_extent_ndims(sid1)) < 0 ) goto error; /* Get the dataspace handle */ if ( (sid2 = H5Dget_space(did2)) < 0 ) goto error; /* Get rank */ if ( (rank2 = H5Sget_simple_extent_ndims(sid2)) < 0 ) goto error; /* Get dimensions */ if ( H5Sget_simple_extent_dims(sid1,dims1,maxdim1) < 0 ) goto error; /* Get dimensions */ if ( H5Sget_simple_extent_dims(sid2,dims2,maxdim2) < 0 ) { goto error; } /*------------------------------------------------------------------------- * get the file data type *------------------------------------------------------------------------- */ /* Get the data type */ if ( (f_tid1 = H5Dget_type(did1)) < 0 ) goto error; /* Get the data type */ if ( (f_tid2 = H5Dget_type(did2)) < 0 ) { goto error; } /*------------------------------------------------------------------------- * check for empty datasets *------------------------------------------------------------------------- */ storage_size1=H5Dget_storage_size(did1); storage_size2=H5Dget_storage_size(did2); if (storage_size1==0 || storage_size2==0) { if ( (options->m_verbose||options->m_list_not_cmp) && obj1_name && obj2_name) parallel_print("Not comparable: <%s> or <%s> is an empty dataset\n", obj1_name, obj2_name); can_compare=0; options->not_cmp=1; } /*------------------------------------------------------------------------- * check for comparable TYPE and SPACE *------------------------------------------------------------------------- */ if (diff_can_type(f_tid1, f_tid2, rank1, rank2, dims1, dims2, maxdim1, maxdim2, obj1_name, obj2_name, options, 0)!=1) { can_compare=0; } /*------------------------------------------------------------------------- * memory type and sizes *------------------------------------------------------------------------- */ if ((m_tid1=h5tools_get_native_type(f_tid1)) < 0) goto error; if ((m_tid2=h5tools_get_native_type(f_tid2)) < 0) goto error; m_size1 = H5Tget_size( m_tid1 ); m_size2 = H5Tget_size( m_tid2 ); /*------------------------------------------------------------------------- * check for different signed/unsigned types *------------------------------------------------------------------------- */ sign1=H5Tget_sign(m_tid1); sign2=H5Tget_sign(m_tid2); if ( sign1 != sign2 ) { if ((options->m_verbose||options->m_list_not_cmp) && obj1_name && obj2_name) { parallel_print("Not comparable: <%s> has sign %s ", obj1_name, get_sign(sign1)); parallel_print("and <%s> has sign %s\n", obj2_name, get_sign(sign2)); } can_compare=0; options->not_cmp=1; } /*------------------------------------------------------------------------- * only attempt to compare if possible *------------------------------------------------------------------------- */ if (can_compare ) /* it is possible to compare */ { /*------------------------------------------------------------------------- * get number of elements *------------------------------------------------------------------------- */ nelmts1 = 1; for (i = 0; i < rank1; i++) { nelmts1 *= dims1[i]; } nelmts2 = 1; for (i = 0; i < rank2; i++) { nelmts2 *= dims2[i]; } assert(nelmts1==nelmts2); /*------------------------------------------------------------------------- * "upgrade" the smaller memory size *------------------------------------------------------------------------- */ if ( m_size1 != m_size2 ) { if ( m_size1 < m_size2 ) { H5Tclose(m_tid1); if ((m_tid1=h5tools_get_native_type(f_tid2)) < 0) goto error; m_size1 = H5Tget_size( m_tid1 ); } else { H5Tclose(m_tid2); if ((m_tid2=h5tools_get_native_type(f_tid1)) < 0) goto error; m_size2 = H5Tget_size( m_tid2 ); } } assert(m_size1==m_size2); /* print names */ if (obj1_name) { name1=diff_basename(obj1_name); } if (obj2_name) { name2=diff_basename(obj2_name); } /*------------------------------------------------------------------------- * read/compare *------------------------------------------------------------------------- */ need = (size_t)(nelmts1*m_size1); /* bytes needed */ if ( need < H5TOOLS_MALLOCSIZE) { buf1 = HDmalloc(need); buf2 = HDmalloc(need); } if ( buf1!=NULL && buf2!=NULL) { if ( H5Dread(did1,m_tid1,H5S_ALL,H5S_ALL,H5P_DEFAULT,buf1) < 0 ) goto error; if ( H5Dread(did2,m_tid2,H5S_ALL,H5S_ALL,H5P_DEFAULT,buf2) < 0 ) goto error; /* array diff */ nfound = diff_array(buf1, buf2, nelmts1, (hsize_t)0, rank1, dims1, options, name1, name2, m_tid1, did1, did2); } else /* possibly not enough memory, read/compare by hyperslabs */ { size_t p_type_nbytes = m_size1; /*size of memory type */ hsize_t p_nelmts = nelmts1; /*total selected elmts */ hsize_t elmtno; /*counter */ int carry; /*counter carry value */ unsigned int vl_data = 0; /*contains VL datatypes */ /* stripmine info */ hsize_t sm_size[H5S_MAX_RANK]; /*stripmine size */ hsize_t sm_nbytes; /*bytes per stripmine */ hsize_t sm_nelmts; /*elements per stripmine*/ hid_t sm_space; /*stripmine data space */ /* hyperslab info */ hsize_t hs_offset[H5S_MAX_RANK]; /*starting offset */ hsize_t hs_size[H5S_MAX_RANK]; /*size this pass */ hsize_t hs_nelmts; /*elements in request */ hsize_t zero[8]; /*vector of zeros */ /* check if we have VL data in the dataset's datatype */ if (H5Tdetect_class(m_tid1, H5T_VLEN) == TRUE) vl_data = TRUE; /* * determine the strip mine size and allocate a buffer. The strip mine is * a hyperslab whose size is manageable. */ sm_nbytes = p_type_nbytes; for (i = rank1; i > 0; --i) { hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes; if ( size == 0) /* datum size > H5TOOLS_BUFSIZE */ size = 1; sm_size[i - 1] = MIN(dims1[i - 1], size); sm_nbytes *= sm_size[i - 1]; assert(sm_nbytes > 0); } sm_buf1 = malloc((size_t)sm_nbytes); sm_buf2 = malloc((size_t)sm_nbytes); sm_nelmts = sm_nbytes / p_type_nbytes; sm_space = H5Screate_simple(1, &sm_nelmts, NULL); /* the stripmine loop */ memset(hs_offset, 0, sizeof hs_offset); memset(zero, 0, sizeof zero); for (elmtno = 0; elmtno < p_nelmts; elmtno += hs_nelmts) { /* calculate the hyperslab size */ if (rank1 > 0) { for (i = 0, hs_nelmts = 1; i < rank1; i++) { hs_size[i] = MIN(dims1[i] - hs_offset[i], sm_size[i]); hs_nelmts *= hs_size[i]; } if (H5Sselect_hyperslab(sid1, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0) goto error; if (H5Sselect_hyperslab(sid2, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0) goto error; if (H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &hs_nelmts, NULL) < 0) goto error; } else { H5Sselect_all(sid1); H5Sselect_all(sid2); H5Sselect_all(sm_space); hs_nelmts = 1; } /* rank */ if ( H5Dread(did1,m_tid1,sm_space,sid1,H5P_DEFAULT,sm_buf1) < 0 ) goto error; if ( H5Dread(did2,m_tid2,sm_space,sid2,H5P_DEFAULT,sm_buf2) < 0 ) goto error; /* get array differences. in the case of hyperslab read, increment the number of differences found in each hyperslab and pass the position at the beggining for printing */ nfound += diff_array(sm_buf1, sm_buf2, hs_nelmts, elmtno, rank1, dims1, options, name1, name2, m_tid1, did1, did2); /* reclaim any VL memory, if necessary */ if(vl_data) { H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf1); H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf2); } /* calculate the next hyperslab offset */ for (i = rank1, carry = 1; i > 0 && carry; --i) { hs_offset[i - 1] += hs_size[i - 1]; if (hs_offset[i - 1] == dims1[i - 1]) hs_offset[i - 1] = 0; else carry = 0; } /* i */ } /* elmtno */ H5Sclose(sm_space); /* free */ if (sm_buf1!=NULL) { free(sm_buf1); sm_buf1=NULL; } if (sm_buf2!=NULL) { free(sm_buf2); sm_buf2=NULL; } } /* hyperslab read */ }/*can_compare*/ /*------------------------------------------------------------------------- * compare attributes * the if condition refers to cases when the dataset is a referenced object *------------------------------------------------------------------------- */ if (obj1_name) { nfound += diff_attr(did1,did2,obj1_name,obj2_name,options); } /*------------------------------------------------------------------------- * close *------------------------------------------------------------------------- */ /* free */ if (buf1!=NULL) { free(buf1); buf1=NULL; } if (buf2!=NULL) { free(buf2); buf2=NULL; } if (sm_buf1!=NULL) { free(sm_buf1); sm_buf1=NULL; } if (sm_buf2!=NULL) { free(sm_buf2); sm_buf2=NULL; } H5E_BEGIN_TRY { H5Sclose(sid1); H5Sclose(sid2); H5Tclose(f_tid1); H5Tclose(f_tid2); H5Tclose(m_tid1); H5Tclose(m_tid2); } H5E_END_TRY; return nfound; error: options->err_stat=1; /* free */ if (buf1!=NULL) { free(buf1); buf1=NULL; } if (buf2!=NULL) { free(buf2); buf2=NULL; } if (sm_buf1!=NULL) { free(sm_buf1); sm_buf1=NULL; } if (sm_buf2!=NULL) { free(sm_buf2); sm_buf2=NULL; } /* disable error reporting */ H5E_BEGIN_TRY { H5Sclose(sid1); H5Sclose(sid2); H5Tclose(f_tid1); H5Tclose(f_tid2); H5Tclose(m_tid1); H5Tclose(m_tid2); /* enable error reporting */ } H5E_END_TRY; return nfound; }
int main (void) { hid_t file, filetype, memtype, space, dset; /* Handles */ herr_t status; hsize_t dims[1] = {DIM0}; char *wdata[DIM0] = {"Parting", "is such", "sweet", "sorrow."}, /* Write buffer */ **rdata; /* Read buffer */ int ndims, i; /* * Create a new file using the default properties. */ file = H5Fcreate (FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); /* * Create file and memory datatypes. For this example we will save * the strings as FORTRAN strings. */ filetype = H5Tcopy (H5T_FORTRAN_S1); status = H5Tset_size (filetype, H5T_VARIABLE); memtype = H5Tcopy (H5T_C_S1); status = H5Tset_size (memtype, H5T_VARIABLE); /* * Create dataspace. Setting maximum size to NULL sets the maximum * size to be the current size. */ space = H5Screate_simple (1, dims, NULL); /* * Create the dataset and write the variable-length string data to * it. */ dset = H5Dcreate (file, DATASET, filetype, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); /* * Close and release resources. */ status = H5Dclose (dset); status = H5Sclose (space); status = H5Tclose (filetype); status = H5Tclose (memtype); status = H5Fclose (file); /* * Now we begin the read section of this example. Here we assume * the dataset has the same name and rank, but can have any size. * Therefore we must allocate a new array to read in data using * malloc(). */ /* * Open file and dataset. */ file = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT); dset = H5Dopen (file, DATASET, H5P_DEFAULT); /* * Get the datatype. */ filetype = H5Dget_type (dset); /* * Get dataspace and allocate memory for read buffer. */ space = H5Dget_space (dset); ndims = H5Sget_simple_extent_dims (space, dims, NULL); rdata = (char **) malloc (dims[0] * sizeof (char *)); /* * Create the memory datatype. */ memtype = H5Tcopy (H5T_C_S1); status = H5Tset_size (memtype, H5T_VARIABLE); /* * Read the data. */ status = H5Dread (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); /* * Output the data to the screen. */ for (i=0; i<dims[0]; i++) printf ("%s[%d]: %s\n", DATASET, i, rdata[i]); /* * Close and release resources. Note that H5Dvlen_reclaim works * for variable-length strings as well as variable-length arrays. * Also note that we must still free the array of pointers stored * in rdata, as H5Tvlen_reclaim only frees the data these point to. */ status = H5Dvlen_reclaim (memtype, space, H5P_DEFAULT, rdata); free (rdata); status = H5Dclose (dset); status = H5Sclose (space); status = H5Tclose (filetype); status = H5Tclose (memtype); status = H5Fclose (file); return 0; }
/**************************************************************** ** ** test_compact_vlstring(): Test code for storing VL strings in ** compact datasets. ** ****************************************************************/ static void test_compact_vlstring(void) { const char *wdata[SPACE1_DIM1] = {"one", "two", "three", "four"}; char *rdata[SPACE1_DIM1]; /* Information read in */ hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ hid_t plist; /* Dataset creation property list */ hsize_t dims1[] = {SPACE1_DIM1}; unsigned i; /* counting variable */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing VL Strings in compact dataset\n")); /* Create file */ fid1 = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); /* Create dataspace for datasets */ sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Create a datatype to refer to */ tid1 = H5Tcopy (H5T_C_S1); CHECK(tid1, FAIL, "H5Tcopy"); ret = H5Tset_size (tid1,H5T_VARIABLE); CHECK(ret, FAIL, "H5Tset_size"); plist = H5Pcreate(H5P_DATASET_CREATE); CHECK(plist, FAIL, "H5Pcreate"); ret = H5Pset_layout(plist, H5D_COMPACT); CHECK(ret, FAIL, "H5Pset_layout"); /* Create a dataset */ dataset = H5Dcreate2(fid1, "Dataset5", tid1, sid1, H5P_DEFAULT, plist, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Write dataset to disk */ ret = H5Dwrite(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); CHECK(ret, FAIL, "H5Dwrite"); /* Read dataset from disk */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dread"); /* Compare data read in */ for(i = 0; i < SPACE1_DIM1; i++) { if(HDstrlen(wdata[i]) != HDstrlen(rdata[i])) { TestErrPrintf("VL data length don't match!, strlen(wdata[%d])=%d, strlen(rdata[%d])=%d\n",(int)i,(int)strlen(wdata[i]),(int)i,(int)strlen(rdata[i])); continue; } /* end if */ if(HDstrcmp(wdata[i], rdata[i]) != 0) { TestErrPrintf("VL data values don't match!, wdata[%d]=%s, rdata[%d]=%s\n",(int)i,wdata[i],(int)i,rdata[i]); continue; } /* end if */ } /* end for */ /* Reclaim the read VL data */ ret = H5Dvlen_reclaim(tid1, sid1, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Close datatype */ ret = H5Tclose(tid1); CHECK(ret, FAIL, "H5Tclose"); /* Close disk dataspace */ ret = H5Sclose(sid1); CHECK(ret, FAIL, "H5Sclose"); /* Close dataset create property list */ ret = H5Pclose(plist); CHECK(ret, FAIL, "H5Pclose"); /* Close file */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); } /*test_compact_vlstrings*/
/**************************************************************** ** ** test_vlstrings_special(): Test VL string code for special ** string cases, nil and zero-sized. ** ****************************************************************/ static void test_vlstrings_special(void) { const char *wdata[SPACE1_DIM1] = {"", "two", "three", "\0"}; const char *wdata2[SPACE1_DIM1] = {NULL, NULL, NULL, NULL}; char *rdata[SPACE1_DIM1]; /* Information read in */ char *fill; /* Fill value */ hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ hid_t dcpl; /* Dataset creation property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; unsigned i; /* counting variable */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Special VL Strings\n")); /* Create file */ fid1 = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); /* Create dataspace for datasets */ sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Create a datatype to refer to */ tid1 = H5Tcopy(H5T_C_S1); CHECK(tid1, FAIL, "H5Tcopy"); ret = H5Tset_size(tid1,H5T_VARIABLE); CHECK(ret, FAIL, "H5Tset_size"); /* Create a dataset */ dataset = H5Dcreate2(fid1, "Dataset3", tid1, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Read from dataset before writing data */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dread"); /* Check data read in */ for(i = 0; i < SPACE1_DIM1; i++) if(rdata[i] != NULL) TestErrPrintf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); /* Write dataset to disk */ ret = H5Dwrite(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); CHECK(ret, FAIL, "H5Dwrite"); /* Read dataset from disk */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dread"); /* Compare data read in */ for(i = 0; i < SPACE1_DIM1; i++) { if(HDstrlen(wdata[i]) != HDstrlen(rdata[i])) { TestErrPrintf("VL data length don't match!, strlen(wdata[%d])=%d, strlen(rdata[%d])=%d\n",(int)i,(int)strlen(wdata[i]),(int)i,(int)strlen(rdata[i])); continue; } /* end if */ if((wdata[i] == NULL && rdata[i] != NULL) || (rdata[i] == NULL && wdata[i] != NULL)) { TestErrPrintf("VL data values don't match!\n"); continue; } /* end if */ if(HDstrcmp(wdata[i], rdata[i]) != 0 ) { TestErrPrintf("VL data values don't match!, wdata[%d]=%s, rdata[%d]=%s\n",(int)i,wdata[i],(int)i,rdata[i]); continue; } /* end if */ } /* end for */ /* Reclaim the read VL data */ ret = H5Dvlen_reclaim(tid1, sid1, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Create another dataset to test nil strings */ dcpl = H5Pcreate(H5P_DATASET_CREATE); CHECK(dcpl, FAIL, "H5Pcreate"); /* Set the fill value for the second dataset */ fill = NULL; ret = H5Pset_fill_value(dcpl, tid1, &fill); CHECK(ret, FAIL, "H5Pset_fill_value"); dataset = H5Dcreate2(fid1, "Dataset4", tid1, sid1, H5P_DEFAULT, dcpl, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Close dataset creation property list */ ret = H5Pclose(dcpl); CHECK(ret, FAIL, "H5Pclose"); /* Read from dataset before writing data */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dread"); /* Check data read in */ for(i = 0; i < SPACE1_DIM1; i++) if(rdata[i] != NULL) TestErrPrintf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); /* Try to write nil strings to disk. */ ret = H5Dwrite(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata2); CHECK(ret, FAIL, "H5Dwrite"); /* Read nil strings back from disk */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); CHECK(ret, FAIL, "H5Dread"); /* Check data read in */ for(i = 0; i < SPACE1_DIM1; i++) if(rdata[i] != NULL) TestErrPrintf("VL doesn't match!, rdata[%d]=%p\n",(int)i,rdata[i]); /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Close datatype */ ret = H5Tclose(tid1); CHECK(ret, FAIL, "H5Tclose"); /* Close disk dataspace */ ret = H5Sclose(sid1); CHECK(ret, FAIL, "H5Sclose"); /* Close file */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); }
/**************************************************************** ** ** test_vlstrings_basic(): Test basic VL string code. ** Tests simple VL string I/O ** ****************************************************************/ static void test_vlstrings_basic(void) { const char *wdata[SPACE1_DIM1]= { "Four score and seven years ago our forefathers brought forth on this continent a new nation,", "conceived in liberty and dedicated to the proposition that all men are created equal.", "Now we are engaged in a great civil war,", "testing whether that nation or any nation so conceived and so dedicated can long endure." }; /* Information to write */ char *rdata[SPACE1_DIM1]; /* Information read in */ char *wdata2; hid_t dataspace, dataset2; hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ hid_t xfer_pid; /* Dataset transfer property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; hsize_t size; /* Number of bytes which will be used */ unsigned i; /* counting variable */ size_t str_used; /* String data in memory */ size_t mem_used=0; /* Memory used during allocation */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Basic VL String Functionality\n")); /* Create file */ fid1 = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(fid1, FAIL, "H5Fcreate"); /* Create dataspace for datasets */ sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL); CHECK(sid1, FAIL, "H5Screate_simple"); /* Create a datatype to refer to */ tid1 = H5Tcopy(H5T_C_S1); CHECK(tid1, FAIL, "H5Tcopy"); ret = H5Tset_size(tid1,H5T_VARIABLE); CHECK(ret, FAIL, "H5Tset_size"); /* Create a dataset */ dataset = H5Dcreate2(fid1, "Dataset1", tid1, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Write dataset to disk */ ret = H5Dwrite(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); CHECK(ret, FAIL, "H5Dwrite"); dataspace = H5Screate(H5S_SCALAR); dataset2 = H5Dcreate2(fid1, "Dataset2", tid1, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); wdata2 = (char*)HDcalloc((size_t)65534, sizeof(char)); HDmemset(wdata2, 'A', (size_t)65533); ret = H5Dwrite(dataset2, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata2); CHECK(ret, FAIL, "H5Dwrite"); H5Sclose(dataspace); H5Dclose(dataset2); HDfree(wdata2); /* Change to the custom memory allocation routines for reading VL string */ xfer_pid = H5Pcreate(H5P_DATASET_XFER); CHECK(xfer_pid, FAIL, "H5Pcreate"); ret=H5Pset_vlen_mem_manager(xfer_pid,test_vlstr_alloc_custom,&mem_used,test_vlstr_free_custom,&mem_used); CHECK(ret, FAIL, "H5Pset_vlen_mem_manager"); /* Make certain the correct amount of memory will be used */ ret=H5Dvlen_get_buf_size(dataset,tid1,sid1,&size); CHECK(ret, FAIL, "H5Dvlen_get_buf_size"); /* Count the actual number of bytes used by the strings */ for(i=0,str_used=0; i<SPACE1_DIM1; i++) str_used+=HDstrlen(wdata[i])+1; /* Compare against the strings actually written */ VERIFY(size,(hsize_t)str_used,"H5Dvlen_get_buf_size"); /* Read dataset from disk */ ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, xfer_pid, rdata); CHECK(ret, FAIL, "H5Dread"); /* Make certain the correct amount of memory has been used */ VERIFY(mem_used,str_used,"H5Dread"); /* Compare data read in */ for(i = 0; i < SPACE1_DIM1; i++) { if(HDstrlen(wdata[i]) != HDstrlen(rdata[i])) { TestErrPrintf("VL data length don't match!, strlen(wdata[%d])=%d, strlen(rdata[%d])=%d\n",(int)i,(int)strlen(wdata[i]),(int)i,(int)strlen(rdata[i])); continue; } /* end if */ if(HDstrcmp(wdata[i], rdata[i]) != 0 ) { TestErrPrintf("VL data values don't match!, wdata[%d]=%s, rdata[%d]=%s\n",(int)i,wdata[i],(int)i,rdata[i]); continue; } /* end if */ } /* end for */ /* Reclaim the read VL data */ ret = H5Dvlen_reclaim(tid1,sid1,xfer_pid,rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); /* Make certain the VL memory has been freed */ VERIFY(mem_used,0,"H5Dvlen_reclaim"); /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Close datatype */ ret = H5Tclose(tid1); CHECK(ret, FAIL, "H5Tclose"); /* Close disk dataspace */ ret = H5Sclose(sid1); CHECK(ret, FAIL, "H5Sclose"); /* Close dataset transfer property list */ ret = H5Pclose(xfer_pid); CHECK(ret, FAIL, "H5Pclose"); /* Close file */ ret = H5Fclose(fid1); CHECK(ret, FAIL, "H5Fclose"); } /* end test_vlstrings_basic() */
herr_t H5AreadVL_asstr (JNIEnv *env, hid_t aid, hid_t tid, jobjectArray buf) { jint i; jint n; hid_t sid; jstring jstr; h5str_t h5str; hvl_t *rdata; hsize_t dims[H5S_MAX_RANK]; size_t size; size_t max_len = 0; herr_t status = -1; /* Get size of string array */ n = ENVPTR->GetArrayLength(ENVPAR buf); /* we will need to read n number of hvl_t structures */ rdata = (hvl_t*)HDcalloc((size_t)n, sizeof(hvl_t)); if (rdata == NULL) { h5JNIFatalError(env, "H5AreadVL_asstr: failed to allocate buff for read"); } /* end if */ else { status = H5Aread(aid, tid, rdata); if (status < 0) { dims[0] = (hsize_t)n; sid = H5Screate_simple(1, dims, NULL); H5Dvlen_reclaim(tid, sid, H5P_DEFAULT, rdata); H5Sclose(sid); HDfree(rdata); h5JNIFatalError(env, "H5AreadVL_asstr: failed to read data"); } /* end if */ else { /* calculate the largest size of all the hvl_t structures read */ max_len = 1; for (i=0; i < n; i++) { if ((rdata + i)->len > max_len) max_len = (rdata + i)->len; } /* create one malloc to hold largest element */ size = H5Tget_size(tid) * max_len; HDmemset(&h5str, 0, sizeof(h5str_t)); h5str_new(&h5str, 4 * size); if (h5str.s == NULL) { dims[0] = (hsize_t)n; sid = H5Screate_simple(1, dims, NULL); H5Dvlen_reclaim(tid, sid, H5P_DEFAULT, rdata); H5Sclose(sid); HDfree(rdata); h5JNIFatalError(env, "H5AreadVL_asstr: failed to allocate buf"); } /* end if */ else { H5T_class_t tclass = H5Tget_class(tid); /* convert each element to char string */ for (i=0; i < n; i++) { h5str.s[0] = '\0'; h5str_vlsprintf(&h5str, aid, tid, rdata+i, 0); jstr = ENVPTR->NewStringUTF(ENVPAR h5str.s); ENVPTR->SetObjectArrayElement(ENVPAR buf, i, jstr); } /* end for */ h5str_free(&h5str); dims[0] = (hsize_t)n; sid = H5Screate_simple(1, dims, NULL); H5Dvlen_reclaim(tid, sid, H5P_DEFAULT, rdata); H5Sclose(sid); HDfree(rdata); } /* end else */ } /* end else */ } /* end else */ return status; }