mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-27 08:49:16 +08:00
100 lines
2.9 KiB
C
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;
|
|
}
|