netcdf-c/libhdf4/hdf4var.c
2019-07-04 10:23:11 -06:00

100 lines
2.9 KiB
C

/* 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 <nc4internal.h>
#include "hdf4dispatch.h"
#include "nc4dispatch.h"
#include <mfhdf.h>
/**
* 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)))
return retval;
free(data);
if (range_error)
return range_error;
}
return NC_NOERR;
}