/* Copyright 2018, UCAR/Unidata See netcdf/COPYRIGHT file for copying * and redistribution conditions.*/ /** * @file @internal This file handles the variable functions for the * HDF4 dispatch layer. * * @author Ed Hartnett */ #include "config.h" #include #include "hdf4dispatch.h" #include "nc4dispatch.h" #include /** * Read an array of values. This is called by nc_get_vara() for * netCDF-4 files, as well as all the other nc_get_vara_* * functions. HDF4 files are handled as a special case. * * @param ncid File ID. * @param varid Variable ID. * @param startp Array of start indices. * @param countp Array of counts. * @param ip pointer that gets the data. * @param memtype The type of these data after it is read into memory. * * @return ::NC_NOERR for success. * @return ::NC_EBADID Bad ncid. * @return ::NC_EINVAL Invalid input. * @return ::NC_EHDFERR HDF4 error. * @return ::NC_ENOMEM Out of memory. * @author Ed Hartnett, Dennis Heimbigner */ int NC_HDF4_get_vara(int ncid, int varid, const size_t *startp, const size_t *countp, void *ip, int memtype) { NC_VAR_HDF4_INFO_T *hdf4_var; NC_VAR_INFO_T *var; int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS]; size_t nelem = 1; void *data; int retval, d; int range_error; LOG((2, "%s: ncid 0x%x varid %d memtype %d", __func__, ncid, varid, memtype)); /* No scalars in HDF4 SD API. Caller must also provide place to put * data. */ if (!startp || !countp || !ip) return NC_EINVAL; /* Find our metadata for this file, group, and var. */ if ((retval = nc4_find_grp_h5_var(ncid, varid, NULL, NULL, &var))) return retval; assert(var && var->hdr.name && var->format_var_info); /* Get the HDF4 specific var metadata. */ hdf4_var = (NC_VAR_HDF4_INFO_T *)var->format_var_info; /* Convert starts/edges to the int32 type HDF4 wants. Also learn * how many elements of data are being read. */ for (d = 0; d < var->ndims; d++) { start32[d] = startp[d]; edge32[d] = countp[d]; nelem *= countp[d]; } /* If memtype was not give, use variable type. */ if (memtype == NC_NAT) memtype = var->type_info->hdr.id; /* If we need to convert data, allocate temp storage. */ if (var->type_info->hdr.id == memtype) data = ip; else if (!(data = malloc(var->type_info->size * nelem))) return NC_ENOMEM; /* Read the data with HDF4. */ if (SDreaddata(hdf4_var->sdsid, start32, NULL, edge32, data)) return NC_EHDFERR; /* Do we need to convert data? */ if (var->type_info->hdr.id != memtype) { if ((retval = nc4_convert_type(data, ip, var->type_info->hdr.id, memtype, nelem, &range_error, NULL, 0, NC_NOQUANTIZE, 0))) return retval; free(data); if (range_error) return range_error; } return NC_NOERR; }