mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
Fixes for NCF-150, bugs in libsrc4 with handling strings in non-netCDF-4 HDF5 files. Added new test in nc_test4 to verify fixes.
This commit is contained in:
parent
279f910774
commit
fa3fbbcc92
@ -223,7 +223,6 @@ main()
|
||||
if (datasetid > 0)
|
||||
{
|
||||
H5Dclose(datasetid);
|
||||
datasetid = 0;
|
||||
}
|
||||
|
||||
if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
|
||||
|
@ -772,10 +772,11 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid,
|
||||
{
|
||||
if ((is_str = H5Tis_variable_str(native_typeid)) < 0)
|
||||
return NC_EHDFERR;
|
||||
if (is_str)
|
||||
/* Make sure fixed-len strings will work like variable-len strings */
|
||||
if (is_str || H5Tget_size(hdf_typeid) > 1)
|
||||
t = NUM_TYPES - 1;
|
||||
else
|
||||
t = 0;
|
||||
t = 0;
|
||||
}
|
||||
else if (class == H5T_INTEGER || class == H5T_FLOAT)
|
||||
{
|
||||
@ -895,6 +896,9 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
|
||||
{
|
||||
dims[0] = 0;
|
||||
}
|
||||
else if (att->xtype == NC_STRING) {
|
||||
dims[0] = att_npoints;
|
||||
}
|
||||
else if (att->xtype == NC_CHAR)
|
||||
{
|
||||
/* NC_CHAR attributes are written as a scalar in HDF5, of type
|
||||
@ -913,8 +917,8 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All netcdf attributes are 1-D only. */
|
||||
if (att_ndims != 1)
|
||||
/* All netcdf attributes are scalar or 1-D only. */
|
||||
if (att_ndims > 1)
|
||||
BAIL(NC_EATTMETA);
|
||||
|
||||
/* Read the size of this attribute. */
|
||||
@ -1859,9 +1863,9 @@ nc4_rec_read_types(NC_GRP_INFO_T *grp)
|
||||
|
||||
res = H5Literate(grp->hdf_grpid, H5_INDEX_NAME, H5_ITER_INC,
|
||||
&idx, nc4_rec_read_types_cb, (void *)grp);
|
||||
if (res<0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
if (res<0)
|
||||
return NC_EHDFERR;
|
||||
return NC_NOERR; /* everything worked! */
|
||||
}
|
||||
|
||||
|
@ -834,6 +834,7 @@ nc4_get_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
|
||||
|
||||
hid_t file_spaceid = 0, mem_spaceid = 0;
|
||||
hid_t xfer_plistid = 0;
|
||||
hid_t hdf_datasetid;
|
||||
size_t file_type_size;
|
||||
|
||||
hsize_t *xtend_size = NULL, count[NC_MAX_VAR_DIMS];
|
||||
@ -993,6 +994,23 @@ nc4_get_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
|
||||
num_spaces++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fix bug when reading HDF5 files with variable of type
|
||||
* fixed-length string. We need to make it look like a
|
||||
* variable-length string, because that's all netCDF-4 data
|
||||
* model supports, lacking anonymous dimensions. So
|
||||
* variable-length strings are in allocated memory that user has
|
||||
* to free, which we allocate here. */
|
||||
if(var->type_info->class == H5T_STRING &&
|
||||
H5Tget_size(var->type_info->hdf_typeid) > 1 &&
|
||||
!H5Tis_variable_str(var->type_info->hdf_typeid)) {
|
||||
hsize_t fstring_len;
|
||||
if ((fstring_len = H5Tget_size(var->type_info->hdf_typeid)) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
if (!(*(char **)data = malloc(1 + fstring_len)))
|
||||
BAIL(NC_ENOMEM);
|
||||
bufr = *(char **)data;
|
||||
}
|
||||
|
||||
#ifndef HDF5_CONVERT
|
||||
/* Are we going to convert any data? (No converting of compound or
|
||||
@ -1016,7 +1034,8 @@ nc4_get_vara(NC_FILE_INFO_T *nc, int ncid, int varid, const size_t *startp,
|
||||
}
|
||||
else
|
||||
#endif /* ifndef HDF5_CONVERT */
|
||||
bufr = data;
|
||||
if(!bufr)
|
||||
bufr = data;
|
||||
|
||||
/* Get the HDF type of the data in memory. */
|
||||
#ifdef HDF5_CONVERT
|
||||
|
@ -20,7 +20,7 @@ tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3 tst_vars4 \
|
||||
tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2 tst_fillbug \
|
||||
tst_xplatform tst_xplatform2 tst_h_atts2 tst_endian_fill tst_atts \
|
||||
t_type cdm_sea_soundings tst_camrun tst_vl tst_atts1 tst_atts2 \
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync
|
||||
tst_vars2 tst_files5 tst_files6 tst_sync tst_h_strbug
|
||||
|
||||
check_PROGRAMS = $(NC4_TESTS)
|
||||
|
||||
|
193
nc_test4/tst_h_strbug.c
Normal file
193
nc_test4/tst_h_strbug.c
Normal file
@ -0,0 +1,193 @@
|
||||
/* This is part of the netCDF package. Copyright 2005 University
|
||||
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
|
||||
conditions of use.
|
||||
|
||||
This program tests fixes for bugs reported with accessing
|
||||
fixed-length scalar string variables and variable-length scalar
|
||||
string attributes from HDF5 files through the netCDF-4 API.
|
||||
|
||||
Here's a HDF5 sample programs:
|
||||
http://hdf.ncsa.uiuc.edu/training/other-ex5/sample-programs/strings.c
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <nc_tests.h>
|
||||
#include <err_macros.h>
|
||||
#include <hdf5.h>
|
||||
|
||||
#define FILE_NAME "tst_h_strbug.h5"
|
||||
#define VS_ATT_NAME "vsatt"
|
||||
#define FS_ATT_NAME "fsatt"
|
||||
#define VS_VAR_NAME "vsvar"
|
||||
#define FS_VAR_NAME "fsvar"
|
||||
#define V1D_VAR_NAME "v1dvar"
|
||||
#define FSTR_LEN 20
|
||||
#define DIM1 4
|
||||
#define RANK 1
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
char *vs = "variable-length string";
|
||||
char fsdata[] = "fixed-length string";
|
||||
char *v1ddata[DIM1] = {"strings","of","variable","length"};
|
||||
int i;
|
||||
char ch;
|
||||
|
||||
printf("\n*** Creating file for checking fix to bugs in accessing strings from HDF5 non-netcdf-4 file.\n");
|
||||
{
|
||||
hid_t fileid, scalar_spaceid, vstypeid, fstypeid, vsattid, fsattid, vsdsetid, fsdsetid;
|
||||
hid_t class;
|
||||
size_t type_size = FSTR_LEN;
|
||||
hid_t v1dattid, v1ddsetid;
|
||||
hid_t v1dspaceid;
|
||||
hsize_t dims[1] = {DIM1};
|
||||
|
||||
if ((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
|
||||
if ((v1dspaceid = H5Screate_simple(RANK, dims, NULL)) < 0) ERR;
|
||||
|
||||
/* Create variable-length and fixed-length string types. */
|
||||
if ((vstypeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
|
||||
if (H5Tset_size(vstypeid, H5T_VARIABLE) < 0) ERR;
|
||||
|
||||
if ((fstypeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
|
||||
if (H5Tset_size(fstypeid, type_size) < 0) ERR;
|
||||
|
||||
/* Create new file, using default properties. */
|
||||
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
/* Create scalar datasets of variable- and fixed-length strings. */
|
||||
if ((vsdsetid = H5Dcreate (fileid, VS_VAR_NAME, vstypeid, scalar_spaceid,
|
||||
H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Dwrite (vsdsetid, vstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &vs)) ERR;
|
||||
if ((fsdsetid = H5Dcreate (fileid, FS_VAR_NAME, fstypeid, scalar_spaceid,
|
||||
H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Dwrite (fsdsetid, fstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &fsdata)) ERR;
|
||||
|
||||
/* Create 1D dataset of variable-length strings. */
|
||||
if ((v1ddsetid = H5Dcreate (fileid, V1D_VAR_NAME, vstypeid, v1dspaceid,
|
||||
H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Dwrite (v1ddsetid, vstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &v1ddata)) ERR;
|
||||
|
||||
/* Write scalar global attributes of these types. */
|
||||
if ((vsattid = H5Acreate(fileid, VS_ATT_NAME, vstypeid, scalar_spaceid,
|
||||
H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Awrite(vsattid, vstypeid, &vs) < 0) ERR;
|
||||
if ((fsattid = H5Acreate(fileid, FS_ATT_NAME, fstypeid, scalar_spaceid,
|
||||
H5P_DEFAULT)) < 0) ERR;
|
||||
if (H5Awrite(fsattid, fstypeid, &fsdata) < 0) ERR;
|
||||
|
||||
/* Close up. */
|
||||
if (H5Aclose(vsattid) < 0) ERR;
|
||||
if (H5Aclose(fsattid) < 0) ERR;
|
||||
if (H5Sclose(scalar_spaceid) < 0) ERR;
|
||||
if (H5Sclose(v1dspaceid) < 0) ERR;
|
||||
if (H5Tclose(vstypeid) < 0) ERR;
|
||||
if (H5Tclose(fstypeid) < 0) ERR;
|
||||
if (H5Dclose(vsdsetid) < 0) ERR;
|
||||
if (H5Dclose(fsdsetid) < 0) ERR;
|
||||
if (H5Dclose(v1ddsetid) < 0) ERR;
|
||||
if (H5Fclose(fileid) < 0) ERR;
|
||||
}
|
||||
|
||||
printf("*** Checking reading variable-length HDF5 string var through netCDF-4 API...");
|
||||
{
|
||||
int ncid, varid, ndims;
|
||||
nc_type type;
|
||||
char *data_in;
|
||||
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
||||
if (nc_inq_varid(ncid, VS_VAR_NAME, &varid)) ERR;
|
||||
if (nc_inq_vartype(ncid, varid, &type)) ERR;
|
||||
if (type != NC_STRING) ERR;
|
||||
if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
|
||||
if (ndims != 0) ERR;
|
||||
if (nc_get_var_string(ncid, varid, &data_in)) ERR;
|
||||
if (strcmp(vs, data_in)) ERR;
|
||||
if (nc_free_string(1, &data_in)) ERR;
|
||||
if (nc_close(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
printf("*** Checking reading fixed-length HDF5 string var through netCDF-4 API...");
|
||||
{
|
||||
int ncid, varid, ndims;
|
||||
nc_type type;
|
||||
char *data_in;
|
||||
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
||||
if (nc_inq_varid(ncid, FS_VAR_NAME, &varid)) ERR;
|
||||
if (nc_inq_vartype(ncid, varid, &type)) ERR;
|
||||
if (type != NC_STRING) ERR;
|
||||
if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
|
||||
if (ndims != 0) ERR;
|
||||
if (nc_get_var_string(ncid, varid, &data_in)) ERR;
|
||||
if (strcmp(fsdata, data_in)) ERR;
|
||||
if (nc_free_string(1, &data_in)) ERR;
|
||||
if (nc_close(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
printf("*** Checking reading variable-length HDF5 string att through netCDF-4 API...");
|
||||
{
|
||||
int ncid, varid, ndims;
|
||||
nc_type type;
|
||||
size_t len;
|
||||
char *data_in;
|
||||
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
||||
if (nc_inq_att(ncid, NC_GLOBAL, VS_ATT_NAME, &type, &len)) ERR;
|
||||
if (type != NC_STRING) ERR;
|
||||
if (len != 1) ERR;
|
||||
if (nc_get_att_string(ncid, NC_GLOBAL, VS_ATT_NAME, &data_in)) ERR;
|
||||
if (strcmp(vs, data_in)) ERR;
|
||||
if (nc_free_string(1, &data_in)) ERR;
|
||||
if (nc_close(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
printf("*** Checking reading fixed-length HDF5 string att through netCDF-4 API...");
|
||||
{
|
||||
int ncid, varid, ndims;
|
||||
nc_type type;
|
||||
size_t len;
|
||||
char *data_in;
|
||||
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
||||
if (nc_inq_att(ncid, NC_GLOBAL, FS_ATT_NAME, &type, &len)) ERR;
|
||||
if (type != NC_CHAR) ERR;
|
||||
if (len != FSTR_LEN) ERR;
|
||||
if (!(data_in = malloc(len))) ERR;
|
||||
/* if (nc_get_att_string(ncid, NC_GLOBAL, FS_ATT_NAME, &data_in)) ERR; */
|
||||
if (nc_get_att_text(ncid, NC_GLOBAL, FS_ATT_NAME, data_in)) ERR;
|
||||
if (strcmp(fsdata, data_in)) ERR;
|
||||
free(data_in);
|
||||
if (nc_close(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
|
||||
printf("*** Checking reading variable-length HDF5 strings var through netCDF-4 API...");
|
||||
{
|
||||
int ncid, varid, ndims;
|
||||
nc_type type;
|
||||
int *dimids;
|
||||
size_t nstrings;
|
||||
char **data_in;
|
||||
if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
|
||||
if (nc_inq_varid(ncid, V1D_VAR_NAME, &varid)) ERR;
|
||||
if (nc_inq_vartype(ncid, varid, &type)) ERR;
|
||||
if (type != NC_STRING) ERR;
|
||||
if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
|
||||
if (ndims != RANK) ERR;
|
||||
if (!(dimids = malloc(ndims * sizeof(int)))) ERR;
|
||||
if (nc_inq_vardimid(ncid, varid, dimids)) ERR;
|
||||
if (nc_inq_dimlen(ncid, dimids[0], &nstrings)) ERR;
|
||||
if (!(data_in = (char **)malloc(nstrings * sizeof(char *)))) ERR;
|
||||
if (nc_get_var_string(ncid, varid, data_in)) ERR;
|
||||
for (i = 0; i < nstrings; i++) {
|
||||
if(strcmp(v1ddata[i], data_in[i])) ERR;
|
||||
}
|
||||
if (nc_free_string(nstrings, data_in)) ERR;
|
||||
free(data_in);
|
||||
free(dimids);
|
||||
if (nc_close(ncid)) ERR;
|
||||
}
|
||||
SUMMARIZE_ERR;
|
||||
FINAL_RESULTS;
|
||||
}
|
@ -52,7 +52,7 @@ static int option_write_diskless = 0; /* default, don't write output to diskless
|
||||
static int
|
||||
get_grpid(int igrp, int parid, int *ogrpp) {
|
||||
int stat = NC_NOERR;
|
||||
int ogid; /* like igrp but in output file */
|
||||
int ogid = parid; /* like igrp but in output file */
|
||||
#ifdef USE_NETCDF4
|
||||
int inparid;
|
||||
|
||||
@ -63,13 +63,10 @@ get_grpid(int igrp, int parid, int *ogrpp) {
|
||||
NC_CHECK(nc_inq_grpname(igrp, grpname));
|
||||
NC_CHECK(nc_inq_grp_ncid(parid, grpname, &ogid));
|
||||
} else if(stat == NC_ENOGRP) { /* root group */
|
||||
ogid = parid;
|
||||
stat = NC_NOERR;
|
||||
} else {
|
||||
NC_CHECK(stat);
|
||||
}
|
||||
#else
|
||||
ogid = parid;
|
||||
#endif /* USE_NETCDF4 */
|
||||
*ogrpp = ogid;
|
||||
return stat;
|
||||
@ -88,8 +85,8 @@ nc_inq_parid(int ncid, const char *fullname, int *locidp) {
|
||||
char *last_slash;
|
||||
if(parent == NULL) {
|
||||
NC_CHECK(NC_ENOMEM);
|
||||
}
|
||||
last_slash = strrchr(parent, '/');
|
||||
} else
|
||||
last_slash = strrchr(parent, '/');
|
||||
if(last_slash == parent) { /* parent is root */
|
||||
free(parent);
|
||||
parent = strdup(slash);
|
||||
|
@ -908,7 +908,7 @@ pr_attx(
|
||||
)
|
||||
{
|
||||
ncatt_t att; /* attribute */
|
||||
char *attvals;
|
||||
char *attvals = "";
|
||||
int attvalslen = 0;
|
||||
|
||||
NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
|
||||
|
Loading…
Reference in New Issue
Block a user