You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11688 lines
254 KiB
11688 lines
254 KiB
/* Do not edit this file. It is produced from the corresponding .m4 source */
|
|
/*
|
|
* Copyright 1996, University Corporation for Atmospheric Research
|
|
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
|
*/
|
|
/* $Id: putget.c,v 1.3 2005/07/19 23:37:24 andy Exp $ */
|
|
|
|
#include "nc.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include "ncx.h"
|
|
#include "fbits.h"
|
|
#include "onstack.h"
|
|
|
|
#undef MIN /* system may define MIN somewhere and complain */
|
|
#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
|
|
|
|
/* #define ODEBUG 1 */
|
|
|
|
#if ODEBUG
|
|
#include <stdio.h>
|
|
/*
|
|
* Print the values of an array of size_t
|
|
*/
|
|
void
|
|
arrayp(const char *label, size_t count, const size_t *array)
|
|
{
|
|
(void) fprintf(stderr, "%s", label);
|
|
(void) fputc('\t',stderr);
|
|
for(; count > 0; count--, array++)
|
|
(void) fprintf(stderr," %lu", (unsigned long)*array);
|
|
(void) fputc('\n',stderr);
|
|
}
|
|
#endif /* ODEBUG */
|
|
|
|
|
|
/* Begin fill */
|
|
/*
|
|
* This is tunable parameter.
|
|
* It essentially controls the tradeoff between the number of times
|
|
* memcpy() gets called to copy the external data to fill
|
|
* a large buffer vs the number of times its called to
|
|
* prepare the external data.
|
|
*/
|
|
#define NFILL 16
|
|
|
|
|
|
|
|
/*
|
|
* Next 6 type specific functions
|
|
* Fill a some memory with the default special value.
|
|
* Formerly
|
|
NC_arrayfill()
|
|
*/
|
|
static int
|
|
NC_fill_schar(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
schar fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
schar *vp = fillp; /* lower bound of area to be filled */
|
|
const schar *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_BYTE;
|
|
}
|
|
}
|
|
return ncx_putn_schar_schar(xpp, nelems, fillp);
|
|
}
|
|
|
|
static int
|
|
NC_fill_char(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
char fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
char *vp = fillp; /* lower bound of area to be filled */
|
|
const char *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_CHAR;
|
|
}
|
|
}
|
|
return ncx_putn_char_char(xpp, nelems, fillp);
|
|
}
|
|
|
|
static int
|
|
NC_fill_short(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
short fillp[NFILL * sizeof(double)/X_SIZEOF_SHORT];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
short *vp = fillp; /* lower bound of area to be filled */
|
|
const short *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_SHORT;
|
|
}
|
|
}
|
|
return ncx_putn_short_short(xpp, nelems, fillp);
|
|
}
|
|
|
|
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
static int
|
|
NC_fill_int(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
int fillp[NFILL * sizeof(double)/X_SIZEOF_INT];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
int *vp = fillp; /* lower bound of area to be filled */
|
|
const int *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_INT;
|
|
}
|
|
}
|
|
return ncx_putn_int_int(xpp, nelems, fillp);
|
|
}
|
|
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
static int
|
|
NC_fill_int(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
long fillp[NFILL * sizeof(double)/X_SIZEOF_INT];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
long *vp = fillp; /* lower bound of area to be filled */
|
|
const long *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_INT;
|
|
}
|
|
}
|
|
return ncx_putn_int_long(xpp, nelems, fillp);
|
|
}
|
|
|
|
#else
|
|
#error "NC_fill_int implementation"
|
|
#endif
|
|
|
|
static int
|
|
NC_fill_float(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
float fillp[NFILL * sizeof(double)/X_SIZEOF_FLOAT];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
float *vp = fillp; /* lower bound of area to be filled */
|
|
const float *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_FLOAT;
|
|
}
|
|
}
|
|
return ncx_putn_float_float(xpp, nelems, fillp);
|
|
}
|
|
|
|
static int
|
|
NC_fill_double(
|
|
void **xpp,
|
|
size_t nelems) /* how many */
|
|
{
|
|
double fillp[NFILL * sizeof(double)/X_SIZEOF_DOUBLE];
|
|
|
|
assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
|
|
|
|
{
|
|
double *vp = fillp; /* lower bound of area to be filled */
|
|
const double *const end = vp + nelems;
|
|
while(vp < end)
|
|
{
|
|
*vp++ = NC_FILL_DOUBLE;
|
|
}
|
|
}
|
|
return ncx_putn_double_double(xpp, nelems, fillp);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Fill the external space for variable 'varp' values at 'recno'
|
|
* with the appropriate value. If 'varp' is not a record
|
|
* variable, fill the whole thing.
|
|
* Formerly
|
|
xdr_NC_fill()
|
|
*/
|
|
int
|
|
fill_NC_var(NC *ncp, const NC_var *varp, size_t recno)
|
|
{
|
|
char xfillp[NFILL * X_SIZEOF_DOUBLE];
|
|
const size_t step = varp->xsz;
|
|
const size_t nelems = sizeof(xfillp)/step;
|
|
const size_t xsz = varp->xsz * nelems;
|
|
NC_attr **attrpp = NULL;
|
|
off_t offset;
|
|
size_t remaining = varp->len;
|
|
|
|
void *xp;
|
|
int status = NC_NOERR;
|
|
|
|
/*
|
|
* Set up fill value
|
|
*/
|
|
attrpp = NC_findattr(&varp->attrs, _FillValue);
|
|
if( attrpp != NULL )
|
|
{
|
|
/* User defined fill value */
|
|
if( (*attrpp)->type != varp->type || (*attrpp)->nelems != 1 )
|
|
{
|
|
return NC_EBADTYPE;
|
|
}
|
|
else
|
|
{
|
|
/* Use the user defined value */
|
|
char *cp = xfillp;
|
|
const char *const end = &xfillp[sizeof(xfillp)];
|
|
|
|
assert(step <= (*attrpp)->xsz);
|
|
|
|
for( /*NADA*/; cp < end; cp += step)
|
|
{
|
|
(void) memcpy(cp, (*attrpp)->xvalue, step);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* use the default */
|
|
|
|
assert(xsz % X_ALIGN == 0);
|
|
assert(xsz <= sizeof(xfillp));
|
|
|
|
xp = xfillp;
|
|
|
|
switch(varp->type){
|
|
case NC_BYTE :
|
|
status = NC_fill_schar(&xp, nelems);
|
|
break;
|
|
case NC_CHAR :
|
|
status = NC_fill_char(&xp, nelems);
|
|
break;
|
|
case NC_SHORT :
|
|
status = NC_fill_short(&xp, nelems);
|
|
break;
|
|
case NC_INT :
|
|
status = NC_fill_int(&xp, nelems);
|
|
break;
|
|
case NC_FLOAT :
|
|
status = NC_fill_float(&xp, nelems);
|
|
break;
|
|
case NC_DOUBLE :
|
|
status = NC_fill_double(&xp, nelems);
|
|
break;
|
|
default :
|
|
assert("fill_NC_var invalid type" == 0);
|
|
status = NC_EBADTYPE;
|
|
break;
|
|
}
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
assert(xp == xfillp + xsz);
|
|
}
|
|
|
|
/*
|
|
* copyout:
|
|
* xfillp now contains 'nelems' elements of the fill value
|
|
* in external representation.
|
|
*/
|
|
|
|
/*
|
|
* Copy it out.
|
|
*/
|
|
|
|
offset = varp->begin;
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
offset += (off_t)ncp->recsize * recno;
|
|
}
|
|
|
|
assert(remaining > 0);
|
|
for(;;)
|
|
{
|
|
const size_t chunksz = MIN(remaining, ncp->chunk);
|
|
size_t ii;
|
|
assert(chunksz % X_ALIGN == 0);
|
|
|
|
status = ncp->nciop->get(ncp->nciop, offset, chunksz,
|
|
RGN_WRITE, &xp);
|
|
if(status != NC_NOERR)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* fill the chunksz buffer in units of xsz
|
|
*/
|
|
for(ii = 0; ii < chunksz/xsz; ii++)
|
|
{
|
|
(void) memcpy(xp, xfillp, xsz);
|
|
xp = (char *)xp + xsz;
|
|
}
|
|
/*
|
|
* Deal with any remainder
|
|
*/
|
|
{
|
|
const size_t rem = chunksz % xsz;
|
|
if(rem != 0)
|
|
{
|
|
(void) memcpy(xp, xfillp, rem);
|
|
/* xp = (char *)xp + xsz; */
|
|
}
|
|
|
|
}
|
|
|
|
status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
|
|
|
|
if(status != NC_NOERR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
remaining -= chunksz;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += chunksz;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
/* End fill */
|
|
|
|
|
|
/*
|
|
* Add a record containing the fill values.
|
|
*/
|
|
static int
|
|
NCfillrecord(NC *ncp, const NC_var *const *varpp, size_t recno)
|
|
{
|
|
size_t ii = 0;
|
|
for(; ii < ncp->vars.nelems; ii++, varpp++)
|
|
{
|
|
if( !IS_RECVAR(*varpp) )
|
|
{
|
|
continue; /* skip non-record variables */
|
|
}
|
|
{
|
|
const int status = fill_NC_var(ncp, *varpp, recno);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
}
|
|
return NC_NOERR;
|
|
}
|
|
|
|
/*
|
|
* It is advantageous to
|
|
* #define TOUCH_LAST
|
|
* when using memory mapped io.
|
|
*/
|
|
#if TOUCH_LAST
|
|
/*
|
|
* Grow the file to a size which can contain recno
|
|
*/
|
|
static int
|
|
NCtouchlast(NC *ncp, const NC_var *const *varpp, size_t recno)
|
|
{
|
|
int status = NC_NOERR;
|
|
const NC_var *varp = NULL;
|
|
|
|
{
|
|
size_t ii = 0;
|
|
for(; ii < ncp->vars.nelems; ii++, varpp++)
|
|
{
|
|
if( !IS_RECVAR(*varpp) )
|
|
{
|
|
continue; /* skip non-record variables */
|
|
}
|
|
varp = *varpp;
|
|
}
|
|
}
|
|
assert(varp != NULL);
|
|
assert( IS_RECVAR(varp) );
|
|
{
|
|
const off_t offset = varp->begin
|
|
+ (off_t)(recno-1) * (off_t)ncp->recsize
|
|
+ (off_t)(varp->len - varp->xsz);
|
|
void *xp;
|
|
|
|
|
|
status = ncp->nciop->get(ncp->nciop, offset, varp->xsz,
|
|
RGN_WRITE, &xp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
(void)memset(xp, 0, varp->xsz);
|
|
status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
|
|
}
|
|
return status;
|
|
}
|
|
#endif /* TOUCH_LAST */
|
|
|
|
|
|
/*
|
|
* Ensure that the netcdf file has 'numrecs' records,
|
|
* add records and fill as neccessary.
|
|
*/
|
|
static int
|
|
NCvnrecs(NC *ncp, size_t numrecs)
|
|
{
|
|
int status = NC_NOERR;
|
|
|
|
if(numrecs > ncp->numrecs)
|
|
{
|
|
|
|
|
|
#if TOUCH_LAST
|
|
status = NCtouchlast(ncp,
|
|
(const NC_var *const*)ncp->vars.value,
|
|
numrecs);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
#endif /* TOUCH_LAST */
|
|
|
|
set_NC_ndirty(ncp);
|
|
|
|
if(!NC_dofill(ncp))
|
|
{
|
|
/* Go directly to jail, do not pass go */
|
|
ncp->numrecs = numrecs;
|
|
}
|
|
else
|
|
{
|
|
size_t unfilled = numrecs - ncp->numrecs;
|
|
size_t ii;
|
|
|
|
for(ii = 0; ii < unfilled; ii++, ncp->numrecs++)
|
|
{
|
|
status = NCfillrecord(ncp,
|
|
(const NC_var *const*)ncp->vars.value,
|
|
ncp->numrecs);
|
|
if(status != NC_NOERR)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
if(NC_doNsync(ncp))
|
|
{
|
|
status = write_numrecs(ncp);
|
|
}
|
|
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Check whether 'coord' values are valid for the variable.
|
|
*/
|
|
static int
|
|
NCcoordck(NC *ncp, const NC_var *varp, const size_t *coord)
|
|
{
|
|
const size_t *ip;
|
|
size_t *up;
|
|
|
|
if(varp->ndims == 0)
|
|
return NC_NOERR; /* 'scalar' variable */
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*coord > X_INT_MAX)
|
|
return NC_EINVALCOORDS; /* sanity check */
|
|
if(NC_readonly(ncp) && *coord >= ncp->numrecs)
|
|
{
|
|
if(!NC_doNsync(ncp))
|
|
return NC_EINVALCOORDS;
|
|
/* else */
|
|
{
|
|
/* Update from disk and check again */
|
|
const int status = read_numrecs(ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
if(*coord >= ncp->numrecs)
|
|
return NC_EINVALCOORDS;
|
|
}
|
|
}
|
|
ip = coord + 1;
|
|
up = varp->shape + 1;
|
|
}
|
|
else
|
|
{
|
|
ip = coord;
|
|
up = varp->shape;
|
|
}
|
|
|
|
#ifdef CDEBUG
|
|
fprintf(stderr," NCcoordck: coord %ld, count %d, ip %ld\n",
|
|
coord, varp->ndims, ip );
|
|
#endif /* CDEBUG */
|
|
|
|
for(; ip < coord + varp->ndims; ip++, up++)
|
|
{
|
|
|
|
#ifdef CDEBUG
|
|
fprintf(stderr," NCcoordck: ip %p, *ip %ld, up %p, *up %lu\n",
|
|
ip, *ip, up, *up );
|
|
#endif /* CDEBUG */
|
|
|
|
/* cast needed for braindead systems with signed size_t */
|
|
if((unsigned long) *ip >= (unsigned long) *up )
|
|
return NC_EINVALCOORDS;
|
|
}
|
|
|
|
return NC_NOERR;
|
|
}
|
|
|
|
|
|
/*
|
|
* Check whether 'edges' are valid for the variable and 'start'
|
|
*/
|
|
/*ARGSUSED*/
|
|
static int
|
|
NCedgeck(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, const size_t *edges)
|
|
{
|
|
const size_t *const end = start + varp->ndims;
|
|
const size_t *shp = varp->shape;
|
|
|
|
(void)ncp;
|
|
|
|
if(varp->ndims == 0)
|
|
return NC_NOERR; /* 'scalar' variable */
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
start++;
|
|
edges++;
|
|
shp++;
|
|
}
|
|
|
|
for(; start < end; start++, edges++, shp++)
|
|
{
|
|
/* cast needed for braindead systems with signed size_t */
|
|
if((unsigned long) *edges > *shp ||
|
|
(unsigned long) *start + (unsigned long) *edges > *shp)
|
|
{
|
|
return(NC_EEDGE);
|
|
}
|
|
}
|
|
return NC_NOERR;
|
|
}
|
|
|
|
|
|
/*
|
|
* Translate the (variable, coord) pair into a seek index
|
|
*/
|
|
static off_t
|
|
NC_varoffset(const NC *ncp, const NC_var *varp, const size_t *coord)
|
|
{
|
|
if(varp->ndims == 0) /* 'scalar' variable */
|
|
return varp->begin;
|
|
|
|
if(varp->ndims == 1)
|
|
{
|
|
if(IS_RECVAR(varp))
|
|
return varp->begin +
|
|
(off_t)(*coord) * (off_t)ncp->recsize;
|
|
/* else */
|
|
return varp->begin + (off_t)(*coord) * (off_t)varp->xsz;
|
|
}
|
|
/* else */
|
|
{
|
|
off_t lcoord = (off_t)coord[varp->ndims -1];
|
|
|
|
size_t *up = varp->dsizes +1;
|
|
const size_t *ip = coord;
|
|
const size_t *const end = varp->dsizes + varp->ndims;
|
|
|
|
if(IS_RECVAR(varp))
|
|
up++, ip++;
|
|
|
|
for(; up < end; up++, ip++)
|
|
lcoord += *up * *ip;
|
|
|
|
lcoord *= varp->xsz;
|
|
|
|
if(IS_RECVAR(varp))
|
|
lcoord += (off_t)(*coord) * ncp->recsize;
|
|
|
|
lcoord += varp->begin;
|
|
return lcoord;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
putNCvx_char_char(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const char *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_char_char(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
putNCvx_schar_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_schar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_uchar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_short(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_int(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_long(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_float(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_schar_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_schar_double(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
putNCvx_short_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_schar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_uchar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_short(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_int(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_long(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_float(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_short_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_short_double(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
putNCvx_int_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_schar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_uchar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_short(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_int(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_long(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_float(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_int_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_int_double(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
putNCvx_float_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_schar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_uchar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_short(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_int(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_long(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_float(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_float_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_float_double(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
putNCvx_double_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_schar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_uchar(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_short(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_int(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_long(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_float(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
putNCvx_double_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nput = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
RGN_WRITE, &xp);
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_putn_double_double(&xp, nput, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
{
|
|
/* not fatal to the loop */
|
|
status = lstatus;
|
|
}
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset,
|
|
RGN_MODIFIED);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nput;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
putNCv_text(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const char *value)
|
|
{
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
return putNCvx_char_char(ncp, varp, start, nelems, value);
|
|
}
|
|
|
|
static int
|
|
putNCv_schar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const schar *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_schar(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_uchar(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const uchar *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_short(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const short *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_short(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_int(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const int *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_int(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_long(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const long *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_long(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_float(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const float *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_float(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
putNCv_double(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const double *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return putNCvx_schar_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return putNCvx_int_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return putNCvx_float_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_double(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
getNCvx_char_char(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, char *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_char_char(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
getNCvx_schar_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_schar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_uchar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_short(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_int(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_long(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_float(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_schar_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_schar_double(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
getNCvx_short_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_schar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_uchar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_short(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_int(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_long(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_float(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_short_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_short_double(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
getNCvx_int_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_schar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_uchar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_short(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_int(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_long(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_float(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_int_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_int_double(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
getNCvx_float_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_schar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_uchar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_short(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_int(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_long(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_float(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_float_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_float_double(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
getNCvx_double_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_schar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_uchar(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_short(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_int(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_long(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_float(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
getNCvx_double_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
off_t offset = NC_varoffset(ncp, varp, start);
|
|
size_t remaining = varp->xsz * nelems;
|
|
int status = NC_NOERR;
|
|
const void *xp;
|
|
|
|
if(nelems == 0)
|
|
return NC_NOERR;
|
|
|
|
assert(value != NULL);
|
|
|
|
for(;;)
|
|
{
|
|
size_t extent = MIN(remaining, ncp->chunk);
|
|
size_t nget = ncx_howmany(varp->type, extent);
|
|
|
|
int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
|
|
0, (void **)&xp); /* cast away const */
|
|
if(lstatus != NC_NOERR)
|
|
return lstatus;
|
|
|
|
lstatus = ncx_getn_double_double(&xp, nget, value);
|
|
if(lstatus != NC_NOERR && status == NC_NOERR)
|
|
status = lstatus;
|
|
|
|
(void) ncp->nciop->rel(ncp->nciop, offset, 0);
|
|
|
|
remaining -= extent;
|
|
if(remaining == 0)
|
|
break; /* normal loop exit */
|
|
offset += extent;
|
|
value += nget;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
getNCv_schar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, schar *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_schar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_schar(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_uchar(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, uchar *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_uchar(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_short(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, short *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_short(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_short(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_int(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, int *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_int(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_int(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_long(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, long *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_long(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_long(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_float(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, float *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_float(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_float(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
static int
|
|
getNCv_double(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, double *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return NC_ECHAR;
|
|
case NC_BYTE:
|
|
return getNCvx_schar_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_INT:
|
|
return getNCvx_int_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_FLOAT:
|
|
return getNCvx_float_double(ncp, varp, start, nelems,
|
|
value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_double(ncp, varp, start, nelems,
|
|
value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
getNCv_text(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, char *value)
|
|
{
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
return getNCvx_char_char(ncp, varp, start, nelems, value);
|
|
}
|
|
|
|
|
|
/*
|
|
* Copy 'nbytes' contiguous external values
|
|
* from ('inncp', invp', inncoord')
|
|
* to ('outncp', 'outvp', 'outcoord')
|
|
* 'inncp' shouldn't be the same as 'outncp'.
|
|
* Used only by ncvarcopy()
|
|
*/
|
|
static int
|
|
NCxvarcpy(NC *inncp, NC_var *invp, size_t *incoord,
|
|
NC *outncp, NC_var *outvp, size_t *outcoord, size_t nbytes)
|
|
{
|
|
int status;
|
|
off_t inoffset = NC_varoffset(inncp, invp, incoord);
|
|
off_t outoffset = NC_varoffset(outncp, outvp, outcoord);
|
|
void *inxp;
|
|
void *outxp;
|
|
const size_t chunk = MIN(inncp->chunk, outncp->chunk);
|
|
|
|
do {
|
|
const size_t extent = MIN(nbytes, chunk);
|
|
|
|
status = inncp->nciop->get(inncp->nciop, inoffset, extent,
|
|
0, &inxp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
status = outncp->nciop->get(outncp->nciop, outoffset, extent,
|
|
RGN_WRITE, &outxp);
|
|
if(status != NC_NOERR)
|
|
{
|
|
(void) inncp->nciop->rel(inncp->nciop, inoffset, 0);
|
|
break;
|
|
}
|
|
|
|
(void) memcpy(outxp, inxp, extent);
|
|
|
|
status = outncp->nciop->rel(outncp->nciop, outoffset,
|
|
RGN_MODIFIED);
|
|
(void) inncp->nciop->rel(inncp->nciop, inoffset, 0);
|
|
|
|
nbytes -= extent;
|
|
if(nbytes == 0)
|
|
break; /* normal loop exit */
|
|
inoffset += extent;
|
|
outoffset += extent;
|
|
|
|
} while (status == NC_NOERR);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* For ncvar{put,get},
|
|
* find the largest contiguous block from within 'edges'.
|
|
* returns the index to the left of this (which may be -1).
|
|
* Compute the number of contiguous elements and return
|
|
* that in *iocountp.
|
|
* The presence of "record" variables makes this routine
|
|
* overly subtle.
|
|
*/
|
|
static int
|
|
NCiocount(const NC *const ncp, const NC_var *const varp,
|
|
const size_t *const edges,
|
|
size_t *const iocountp)
|
|
{
|
|
const size_t *edp0 = edges;
|
|
const size_t *edp = edges + varp->ndims;
|
|
const size_t *shp = varp->shape + varp->ndims;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only 'record' variable */
|
|
*iocountp = *edges;
|
|
return(0);
|
|
}
|
|
/* else */
|
|
edp0++;
|
|
}
|
|
|
|
assert(edges != NULL);
|
|
|
|
/* find max contiguous */
|
|
while(edp > edp0)
|
|
{
|
|
shp--; edp--;
|
|
if(*edp < *shp )
|
|
{
|
|
const size_t *zedp = edp;
|
|
while(zedp >= edp0)
|
|
{
|
|
if(*zedp == 0)
|
|
{
|
|
*iocountp = 0;
|
|
goto done;
|
|
}
|
|
/* Tip of the hat to segmented architectures */
|
|
if(zedp == edp0)
|
|
break;
|
|
zedp--;
|
|
}
|
|
break;
|
|
}
|
|
assert(*edp == *shp);
|
|
}
|
|
|
|
/*
|
|
* edp, shp reference rightmost index s.t. *(edp +1) == *(shp +1)
|
|
*
|
|
* Or there is only one dimension.
|
|
* If there is only one dimension and it is 'non record' dimension,
|
|
* edp is &edges[0] and we will return -1.
|
|
* If there is only one dimension and and it is a "record dimension",
|
|
* edp is &edges[1] (out of bounds) and we will return 0;
|
|
*/
|
|
assert(shp >= varp->shape + varp->ndims -1
|
|
|| *(edp +1) == *(shp +1));
|
|
|
|
/* now accumulate max count for a single io operation */
|
|
for(*iocountp = 1, edp0 = edp;
|
|
edp0 < edges + varp->ndims;
|
|
edp0++)
|
|
{
|
|
*iocountp *= *edp0;
|
|
}
|
|
|
|
done:
|
|
return((int)(edp - edges) - 1);
|
|
}
|
|
|
|
|
|
/*
|
|
* Set the elements of the array 'upp' to
|
|
* the sum of the corresponding elements of
|
|
* 'stp' and 'edp'. 'end' should be &stp[nelems].
|
|
*/
|
|
static void
|
|
set_upper(size_t *upp, /* modified on return */
|
|
const size_t *stp,
|
|
const size_t *edp,
|
|
const size_t *const end)
|
|
{
|
|
while(upp < end) {
|
|
*upp++ = *stp++ + *edp++;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* The infamous and oft-discussed odometer code.
|
|
*
|
|
* 'start[]' is the starting coordinate.
|
|
* 'upper[]' is the upper bound s.t. start[ii] < upper[ii].
|
|
* 'coord[]' is the register, the current coordinate value.
|
|
* For some ii,
|
|
* upp == &upper[ii]
|
|
* cdp == &coord[ii]
|
|
*
|
|
* Running this routine increments *cdp.
|
|
*
|
|
* If after the increment, *cdp is equal to *upp
|
|
* (and cdp is not the leftmost dimension),
|
|
* *cdp is "zeroed" to the starting value and
|
|
* we need to "carry", eg, increment one place to
|
|
* the left.
|
|
*
|
|
* TODO: Some architectures hate recursion?
|
|
* Reimplement non-recursively.
|
|
*/
|
|
static void
|
|
odo1(const size_t *const start, const size_t *const upper,
|
|
size_t *const coord, /* modified on return */
|
|
const size_t *upp,
|
|
size_t *cdp)
|
|
{
|
|
assert(coord <= cdp && cdp <= coord + NC_MAX_DIMS);
|
|
assert(upper <= upp && upp <= upper + NC_MAX_DIMS);
|
|
assert(upp - upper == cdp - coord);
|
|
|
|
assert(*cdp <= *upp);
|
|
|
|
(*cdp)++;
|
|
if(cdp != coord && *cdp >= *upp)
|
|
{
|
|
*cdp = start[cdp - coord];
|
|
odo1(start, upper, coord, upp -1, cdp -1);
|
|
}
|
|
}
|
|
#ifdef _CRAYC
|
|
#pragma _CRI noinline odo1
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Public */
|
|
|
|
|
|
int
|
|
nc_put_var1_text(int ncid, int varid, const size_t *coord,
|
|
const char *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_text(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_var1_uchar(int ncid, int varid, const size_t *coord,
|
|
const uchar *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_uchar(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_schar(int ncid, int varid, const size_t *coord,
|
|
const schar *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_schar(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_short(int ncid, int varid, const size_t *coord,
|
|
const short *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_short(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_int(int ncid, int varid, const size_t *coord,
|
|
const int *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_int(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_long(int ncid, int varid, const size_t *coord,
|
|
const long *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_long(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_float(int ncid, int varid, const size_t *coord,
|
|
const float *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_float(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_put_var1_double(int ncid, int varid, const size_t *coord,
|
|
const double *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *coord +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
return putNCv_double(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_put_var1(int ncid, int varid, const size_t *coord, const void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return nc_put_var1_text(ncid, varid, coord,
|
|
(const char *) value);
|
|
case NC_BYTE:
|
|
return nc_put_var1_schar(ncid, varid, coord,
|
|
(const schar *) value);
|
|
case NC_SHORT:
|
|
return nc_put_var1_short(ncid, varid, coord,
|
|
(const short *) value);
|
|
case NC_INT:
|
|
return nc_put_var1_int(ncid, varid, coord,
|
|
(const int *) value);
|
|
case NC_FLOAT:
|
|
return nc_put_var1_float(ncid, varid, coord,
|
|
(const float *) value);
|
|
case NC_DOUBLE:
|
|
return nc_put_var1_double(ncid, varid, coord,
|
|
(const double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
nc_get_var1_text(int ncid, int varid, const size_t *coord, char *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_text(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_var1_uchar(int ncid, int varid, const size_t *coord, uchar *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_uchar(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_schar(int ncid, int varid, const size_t *coord, schar *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_schar(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_short(int ncid, int varid, const size_t *coord, short *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_short(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_int(int ncid, int varid, const size_t *coord, int *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_int(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_long(int ncid, int varid, const size_t *coord, long *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_long(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_float(int ncid, int varid, const size_t *coord, float *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_float(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
int
|
|
nc_get_var1_double(int ncid, int varid, const size_t *coord, double *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, coord);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return getNCv_double(ncp, varp, coord, 1, value);
|
|
}
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_get_var1(int ncid, int varid, const size_t *coord, void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return nc_get_var1_text(ncid, varid, coord,
|
|
(char *) value);
|
|
case NC_BYTE:
|
|
return nc_get_var1_schar(ncid, varid, coord,
|
|
(schar *) value);
|
|
case NC_SHORT:
|
|
return nc_get_var1_short(ncid, varid, coord,
|
|
(short *) value);
|
|
case NC_INT:
|
|
return nc_get_var1_int(ncid, varid, coord,
|
|
(int *) value);
|
|
case NC_FLOAT:
|
|
return nc_get_var1_float(ncid, varid, coord,
|
|
(float *) value);
|
|
case NC_DOUBLE:
|
|
return nc_get_var1_double(ncid, varid, coord,
|
|
(double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
nc_put_vara_text(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const char *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_text(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_text(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_text(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_text(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_vara_uchar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const uchar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_uchar(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_uchar(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_uchar(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_uchar(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_schar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const schar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_schar(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_schar(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_schar(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_schar(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_short(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const short *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_short(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_short(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_short(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_short(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_int(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const int *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_int(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_int(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_int(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_int(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_long(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const long *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_long(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_long(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_long(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_long(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_float(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const float *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_float(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_float(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_float(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_float(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_vara_double(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const double *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( putNCv_double(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
status = NCvnrecs(ncp, *start + *edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( putNCv_double(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( putNCv_double(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = putNCv_double(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_put_vara(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, const void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return nc_put_vara_text(ncid, varid, start, edges,
|
|
(const char *) value);
|
|
case NC_BYTE:
|
|
return nc_put_vara_schar(ncid, varid, start, edges,
|
|
(const schar *) value);
|
|
case NC_SHORT:
|
|
return nc_put_vara_short(ncid, varid, start, edges,
|
|
(const short *) value);
|
|
case NC_INT:
|
|
return nc_put_vara_int(ncid, varid, start, edges,
|
|
(const int *) value);
|
|
case NC_FLOAT:
|
|
return nc_put_vara_float(ncid, varid, start, edges,
|
|
(const float *) value);
|
|
case NC_DOUBLE:
|
|
return nc_put_vara_double(ncid, varid, start, edges,
|
|
(const double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
nc_get_vara_text(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, char *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_text(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_text(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_text(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_text(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_vara_uchar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, uchar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_uchar(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_uchar(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_uchar(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_uchar(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_schar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, schar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_schar(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_schar(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_schar(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_schar(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_short(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, short *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_short(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_short(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_short(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_short(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_int(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, int *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_int(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_int(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_int(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_int(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_long(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, long *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_long(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_long(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_long(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_long(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_float(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, float *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_float(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_float(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_float(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_float(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_vara_double(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, double *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
int ii;
|
|
size_t iocount;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
status = NCcoordck(ncp, varp, start);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
status = NCedgeck(ncp, varp, start, edges);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
return( getNCv_double(ncp, varp, start, 1, value) );
|
|
}
|
|
|
|
if(IS_RECVAR(varp))
|
|
{
|
|
if(*start + *edges > ncp->numrecs)
|
|
return NC_EEDGE;
|
|
if(varp->ndims == 1 && ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return( getNCv_double(ncp, varp, start, *edges, value) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* find max contiguous
|
|
* and accumulate max count for a single io operation
|
|
*/
|
|
ii = NCiocount(ncp, varp, edges, &iocount);
|
|
|
|
if(ii == -1)
|
|
{
|
|
return( getNCv_double(ncp, varp, start, iocount, value) );
|
|
}
|
|
|
|
assert(ii >= 0);
|
|
|
|
|
|
{ /* inline */
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
ALLOC_ONSTACK(upper, size_t, varp->ndims);
|
|
const size_t index = ii;
|
|
|
|
/* copy in starting indices */
|
|
(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
|
|
|
|
/* set up in maximum indices */
|
|
set_upper(upper, start, edges, &upper[varp->ndims]);
|
|
|
|
/* ripple counter */
|
|
while(*coord < *upper)
|
|
{
|
|
const int lstatus = getNCv_double(ncp, varp, coord, iocount,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += iocount;
|
|
odo1(start, upper, coord, &upper[index], &coord[index]);
|
|
}
|
|
|
|
FREE_ONSTACK(upper);
|
|
FREE_ONSTACK(coord);
|
|
} /* end inline */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_get_vara(int ncid, int varid,
|
|
const size_t *start, const size_t *edges, void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return nc_get_vara_text(ncid, varid, start, edges,
|
|
(char *) value);
|
|
case NC_BYTE:
|
|
return nc_get_vara_schar(ncid, varid, start, edges,
|
|
(schar *) value);
|
|
case NC_SHORT:
|
|
return nc_get_vara_short(ncid, varid, start, edges,
|
|
(short *) value);
|
|
case NC_INT:
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
return nc_get_vara_int(ncid, varid, start, edges,
|
|
(int *) value);
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
return nc_get_vara_long(ncid, varid, start, edges,
|
|
(long *) value);
|
|
#else
|
|
#error "nc_get_vara implementation"
|
|
#endif
|
|
case NC_FLOAT:
|
|
return nc_get_vara_float(ncid, varid, start, edges,
|
|
(float *) value);
|
|
case NC_DOUBLE:
|
|
return nc_get_vara_double(ncid, varid, start, edges,
|
|
(double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
#if 1 /* defined(__cplusplus) */
|
|
/* C++ consts default to internal linkage and must be initialized */
|
|
static const size_t coord_zero[NC_MAX_VAR_DIMS] = {0};
|
|
#else
|
|
static const size_t coord_zero[NC_MAX_VAR_DIMS];
|
|
#endif
|
|
|
|
|
|
int
|
|
nc_put_var_text(int ncid, int varid, const char *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_text(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_text(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_text(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_text(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_var_uchar(int ncid, int varid, const uchar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_uchar(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_uchar(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_uchar(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_schar(int ncid, int varid, const schar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_schar(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_schar(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_schar(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_short(int ncid, int varid, const short *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_short(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_short(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_short(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_short(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_int(int ncid, int varid, const int *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_int(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_int(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_int(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_int(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_long(int ncid, int varid, const long *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_long(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_long(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_long(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_long(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_float(int ncid, int varid, const float *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_float(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_float(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_float(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_float(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_put_var_double(int ncid, int varid, const double *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
return NC_EPERM;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( putNCv_double(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(putNCv_double(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(putNCv_double(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = putNCv_double(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
nc_get_var_text(int ncid, int varid, char *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_text(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_text(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_text(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_text(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_var_uchar(int ncid, int varid, uchar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_uchar(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_uchar(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_uchar(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_schar(int ncid, int varid, schar *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_schar(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_schar(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_schar(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_short(int ncid, int varid, short *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_short(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_short(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_short(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_short(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_int(int ncid, int varid, int *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_int(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_int(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_int(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_int(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_long(int ncid, int varid, long *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_long(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_long(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_long(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_long(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_float(int ncid, int varid, float *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_float(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_float(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_float(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_float(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
int
|
|
nc_get_var_double(int ncid, int varid, double *value)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
return NC_EINDEFINE;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
|
|
|
|
if(varp->ndims == 0) /* scalar variable */
|
|
{
|
|
const size_t zed = 0;
|
|
return( getNCv_double(ncp, varp, &zed, 1, value) );
|
|
}
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
|
|
if(!IS_RECVAR(varp))
|
|
{
|
|
return(getNCv_double(ncp, varp, coord_zero, *varp->dsizes, value));
|
|
}
|
|
/* else */
|
|
|
|
if(varp->ndims == 1
|
|
&& ncp->recsize <= varp->len)
|
|
{
|
|
/* one dimensional && the only record variable */
|
|
return(getNCv_double(ncp, varp, coord_zero, ncp->numrecs, value));
|
|
}
|
|
/* else */
|
|
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, varp->ndims);
|
|
size_t elemsPerRec = 1;
|
|
(void) memset(coord, 0, varp->ndims * sizeof(size_t));
|
|
/* TODO: fix dsizes to avoid this nonsense */
|
|
if(varp->ndims > 1)
|
|
elemsPerRec = varp->dsizes[1];
|
|
while(*coord < ncp->numrecs)
|
|
{
|
|
const int lstatus = getNCv_double(ncp, varp, coord, elemsPerRec,
|
|
value);
|
|
if(lstatus != NC_NOERR)
|
|
{
|
|
if(lstatus != NC_ERANGE)
|
|
{
|
|
status = lstatus;
|
|
/* fatal for the loop */
|
|
break;
|
|
}
|
|
/* else NC_ERANGE, not fatal for the loop */
|
|
if(status == NC_NOERR)
|
|
status = lstatus;
|
|
}
|
|
value += elemsPerRec;
|
|
(*coord)++;
|
|
}
|
|
FREE_ONSTACK(coord);
|
|
} /* elemsPerRec */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/* Begin putgetg.c */
|
|
|
|
|
|
|
|
int
|
|
nc_get_vars_text (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
char *value)
|
|
{
|
|
return nc_get_varm_text (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_vars_uchar (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
uchar *value)
|
|
{
|
|
return nc_get_varm_uchar (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_schar (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
schar *value)
|
|
{
|
|
return nc_get_varm_schar (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_short (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
short *value)
|
|
{
|
|
return nc_get_varm_short (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_int (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
int *value)
|
|
{
|
|
return nc_get_varm_int (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_long (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
long *value)
|
|
{
|
|
return nc_get_varm_long (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_float (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
float *value)
|
|
{
|
|
return nc_get_varm_float (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_get_vars_double (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
double *value)
|
|
{
|
|
return nc_get_varm_double (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_vars (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
void *value)
|
|
{
|
|
return nc_get_varm (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
|
|
int
|
|
nc_put_vars_text (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const char *value)
|
|
{
|
|
return nc_put_varm_text (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_vars_uchar (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const uchar *value)
|
|
{
|
|
return nc_put_varm_uchar (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_schar (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const schar *value)
|
|
{
|
|
return nc_put_varm_schar (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_short (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const short *value)
|
|
{
|
|
return nc_put_varm_short (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_int (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const int *value)
|
|
{
|
|
return nc_put_varm_int (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_long (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const long *value)
|
|
{
|
|
return nc_put_varm_long (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_float (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const float *value)
|
|
{
|
|
return nc_put_varm_float (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
int
|
|
nc_put_vars_double (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const double *value)
|
|
{
|
|
return nc_put_varm_double (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_vars (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const void *value)
|
|
{
|
|
return nc_put_varm (ncid, varid, start, edges,
|
|
stride, 0, value);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generalized hyperslab input.
|
|
*/
|
|
|
|
int
|
|
nc_get_varm_text(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
char *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_text (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_text()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_text (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
int
|
|
nc_get_varm_uchar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
uchar *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_uchar (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_uchar()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_uchar (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_schar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
schar *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_schar (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_schar()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_schar (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_short(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
short *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_short (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_short()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_short (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_int(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
int *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_int (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_int()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_int (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_long(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
long *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_long (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_long()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_long (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_float(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
float *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_float (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_float()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_float (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_get_varm_double(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride,
|
|
const ptrdiff_t *map,
|
|
double *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return getNCv_double (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
size_t dimlen =
|
|
idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs : varp->shape[idim];
|
|
if (mystart[idim] >= dimlen)
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
|
|
if (mystart[idim] + myedges[idim] > dimlen)
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_get_vara_double()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_get_vara_double (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_get_varm (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const ptrdiff_t * map,
|
|
void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
ptrdiff_t *cvtmap = NULL;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(map != NULL && varp->ndims != 0)
|
|
{
|
|
/*
|
|
* convert map units from bytes to units of sizeof(type)
|
|
*/
|
|
size_t ii;
|
|
const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type);
|
|
cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t));
|
|
if(cvtmap == NULL)
|
|
return NC_ENOMEM;
|
|
for(ii = 0; ii < varp->ndims; ii++)
|
|
{
|
|
if(map[ii] % szof != 0)
|
|
{
|
|
free(cvtmap);
|
|
return NC_EINVAL;
|
|
}
|
|
cvtmap[ii] = map[ii] / szof;
|
|
}
|
|
map = cvtmap;
|
|
}
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
status = nc_get_varm_text(ncid, varid, start, edges,
|
|
stride, map,
|
|
(char *) value);
|
|
break;
|
|
case NC_BYTE:
|
|
status = nc_get_varm_schar(ncid, varid, start, edges,
|
|
stride, map,
|
|
(schar *) value);
|
|
break;
|
|
case NC_SHORT:
|
|
status = nc_get_varm_short(ncid, varid, start, edges,
|
|
stride, map,
|
|
(short *) value);
|
|
break;
|
|
case NC_INT:
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
status = nc_get_varm_int(ncid, varid, start, edges,
|
|
stride, map,
|
|
(int *) value);
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
status = nc_get_varm_long(ncid, varid, start, edges,
|
|
stride, map,
|
|
(long *) value);
|
|
#else
|
|
#error "nc_get_varm implementation"
|
|
#endif
|
|
break;
|
|
case NC_FLOAT:
|
|
status = nc_get_varm_float(ncid, varid, start, edges,
|
|
stride, map,
|
|
(float *) value);
|
|
break;
|
|
case NC_DOUBLE:
|
|
status = nc_get_varm_double(ncid, varid, start, edges,
|
|
stride, map,
|
|
(double *) value);
|
|
break;
|
|
default:
|
|
status = NC_EBADTYPE;
|
|
break;
|
|
}
|
|
|
|
if(cvtmap != NULL)
|
|
{
|
|
free(cvtmap);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Generalized hyperslab output.
|
|
*/
|
|
|
|
int
|
|
nc_put_varm_text(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const char *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type != NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_text (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_text()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_text (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
int
|
|
nc_put_varm_uchar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const uchar *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_uchar (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_uchar()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_uchar (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_schar(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const schar *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_schar (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_schar()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_schar (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_short(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const short *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_short (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_short()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_short (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_int(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const int *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_int (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_int()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_int (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_long(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const long *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_long (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_long()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_long (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_float(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const float *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_float (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_float()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_float (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
int
|
|
nc_put_varm_double(int ncid, int varid,
|
|
const size_t *start, const size_t *edges,
|
|
const ptrdiff_t *stride, const ptrdiff_t *map,
|
|
const double *value)
|
|
{
|
|
int status = ENOERR;
|
|
NC *ncp;
|
|
NC_var *varp;
|
|
int maxidim; /* maximum dimensional index */
|
|
|
|
status = NC_check_id (ncid, &ncp);
|
|
if (status != NC_NOERR)
|
|
return status;
|
|
|
|
if (NC_indef (ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if (NC_readonly (ncp))
|
|
return NC_EPERM;
|
|
varp = NC_lookupvar (ncp, varid);
|
|
if (varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(varp->type == NC_CHAR)
|
|
return NC_ECHAR;
|
|
|
|
maxidim = (int) varp->ndims - 1;
|
|
|
|
if (maxidim < 0)
|
|
{
|
|
/*
|
|
* The variable is a scalar; consequently,
|
|
* there s only one thing to get and only one place to put it.
|
|
* (Why was I called?)
|
|
*/
|
|
return putNCv_double (ncp, varp, start, 1, value);
|
|
}
|
|
|
|
/*
|
|
* else
|
|
* The variable is an array.
|
|
*/
|
|
{
|
|
int idim;
|
|
size_t *mystart = NULL;
|
|
size_t *myedges;
|
|
size_t *iocount; /* count vector */
|
|
size_t *stop; /* stop indexes */
|
|
size_t *length; /* edge lengths in bytes */
|
|
ptrdiff_t *mystride;
|
|
ptrdiff_t *mymap;
|
|
|
|
/*
|
|
* Verify stride argument.
|
|
*/
|
|
for (idim = 0; idim <= maxidim; ++idim)
|
|
{
|
|
if (stride != NULL
|
|
&& (stride[idim] == 0
|
|
/* cast needed for braindead systems with signed size_t */
|
|
|| (unsigned long) stride[idim] >= X_INT_MAX))
|
|
{
|
|
return NC_ESTRIDE;
|
|
}
|
|
}
|
|
|
|
/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
|
|
mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
|
|
if(mystart == NULL)
|
|
return NC_ENOMEM;
|
|
myedges = mystart + varp->ndims;
|
|
iocount = myedges + varp->ndims;
|
|
stop = iocount + varp->ndims;
|
|
length = stop + varp->ndims;
|
|
mystride = (ptrdiff_t *)(length + varp->ndims);
|
|
mymap = mystride + varp->ndims;
|
|
|
|
/*
|
|
* Initialize I/O parameters.
|
|
*/
|
|
for (idim = maxidim; idim >= 0; --idim)
|
|
{
|
|
mystart[idim] = start != NULL
|
|
? start[idim]
|
|
: 0;
|
|
|
|
if (edges[idim] == 0)
|
|
{
|
|
status = NC_NOERR; /* read/write no data */
|
|
goto done;
|
|
}
|
|
|
|
myedges[idim] = edges != NULL
|
|
? edges[idim]
|
|
: idim == 0 && IS_RECVAR (varp)
|
|
? ncp->numrecs - mystart[idim]
|
|
: varp->shape[idim] - mystart[idim];
|
|
mystride[idim] = stride != NULL
|
|
? stride[idim]
|
|
: 1;
|
|
mymap[idim] = map != NULL
|
|
? map[idim]
|
|
: idim == maxidim
|
|
? 1
|
|
: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
|
|
|
|
iocount[idim] = 1;
|
|
length[idim] = mymap[idim] * myedges[idim];
|
|
stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
|
|
}
|
|
|
|
/*
|
|
* Check start, edges
|
|
*/
|
|
for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
|
|
{
|
|
if (mystart[idim] >= varp->shape[idim])
|
|
{
|
|
status = NC_EINVALCOORDS;
|
|
goto done;
|
|
}
|
|
if (mystart[idim] + myedges[idim] > varp->shape[idim])
|
|
{
|
|
status = NC_EEDGE;
|
|
goto done;
|
|
}
|
|
}
|
|
/*
|
|
* As an optimization, adjust I/O parameters when the fastest
|
|
* dimension has unity stride both externally and internally.
|
|
* In this case, the user could have called a simpler routine
|
|
* (i.e. ncvarnc_put_vara_double()
|
|
*/
|
|
if (mystride[maxidim] == 1
|
|
&& mymap[maxidim] == 1)
|
|
{
|
|
iocount[maxidim] = myedges[maxidim];
|
|
mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
|
|
mymap[maxidim] = (ptrdiff_t) length[maxidim];
|
|
}
|
|
|
|
/*
|
|
* Perform I/O. Exit when done.
|
|
*/
|
|
for (;;)
|
|
{
|
|
/* TODO: */
|
|
int lstatus = nc_put_vara_double (ncid, varid, mystart, iocount,
|
|
value);
|
|
if (lstatus != NC_NOERR
|
|
&& (status == NC_NOERR || lstatus != NC_ERANGE))
|
|
status = lstatus;
|
|
|
|
/*
|
|
* The following code permutes through the variable s
|
|
* external start-index space and it s internal address
|
|
* space. At the UPC, this algorithm is commonly
|
|
* called "odometer code".
|
|
*/
|
|
idim = maxidim;
|
|
carry:
|
|
value += mymap[idim];
|
|
mystart[idim] += mystride[idim];
|
|
if (mystart[idim] == stop[idim])
|
|
{
|
|
mystart[idim] = start[idim];
|
|
value -= length[idim];
|
|
if (--idim < 0)
|
|
break; /* normal return */
|
|
goto carry;
|
|
}
|
|
} /* I/O loop */
|
|
done:
|
|
free(mystart);
|
|
} /* variable is array */
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* deprecated, used to support the 2.x interface */
|
|
int
|
|
nc_put_varm (
|
|
int ncid,
|
|
int varid,
|
|
const size_t * start,
|
|
const size_t * edges,
|
|
const ptrdiff_t * stride,
|
|
const ptrdiff_t * map,
|
|
const void *value)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
const NC_var *varp;
|
|
ptrdiff_t *cvtmap = NULL;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
varp = NC_lookupvar(ncp, varid);
|
|
if(varp == NULL)
|
|
return NC_ENOTVAR;
|
|
|
|
if(map != NULL && varp->ndims != 0)
|
|
{
|
|
/*
|
|
* convert map units from bytes to units of sizeof(type)
|
|
*/
|
|
size_t ii;
|
|
const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type);
|
|
cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t));
|
|
if(cvtmap == NULL)
|
|
return NC_ENOMEM;
|
|
for(ii = 0; ii < varp->ndims; ii++)
|
|
{
|
|
if(map[ii] % szof != 0)
|
|
{
|
|
free(cvtmap);
|
|
return NC_EINVAL;
|
|
}
|
|
cvtmap[ii] = map[ii] / szof;
|
|
}
|
|
map = cvtmap;
|
|
}
|
|
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
status = nc_put_varm_text(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const char *) value);
|
|
break;
|
|
case NC_BYTE:
|
|
status = nc_put_varm_schar(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const schar *) value);
|
|
break;
|
|
case NC_SHORT:
|
|
status = nc_put_varm_short(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const short *) value);
|
|
break;
|
|
case NC_INT:
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
status = nc_put_varm_int(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const int *) value);
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
status = nc_put_varm_long(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const long *) value);
|
|
#else
|
|
#error "nc_put_varm implementation"
|
|
#endif
|
|
break;
|
|
case NC_FLOAT:
|
|
status = nc_put_varm_float(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const float *) value);
|
|
break;
|
|
case NC_DOUBLE:
|
|
status = nc_put_varm_double(ncid, varid, start, edges,
|
|
stride, map,
|
|
(const double *) value);
|
|
break;
|
|
default:
|
|
status = NC_EBADTYPE;
|
|
break;
|
|
}
|
|
|
|
if(cvtmap != NULL)
|
|
{
|
|
free(cvtmap);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/* Begin recio, deprecated */
|
|
|
|
/*
|
|
* input 'nelems' items of contiguous data of 'varp' at 'start'
|
|
* N.B. this function deprecated.
|
|
*/
|
|
static int
|
|
getNCvdata(const NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, void *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return getNCvx_char_char(ncp, varp, start, nelems,
|
|
(char *) value);
|
|
case NC_BYTE:
|
|
return getNCvx_schar_schar(ncp, varp, start, nelems,
|
|
(schar *) value);
|
|
case NC_SHORT:
|
|
return getNCvx_short_short(ncp, varp, start, nelems,
|
|
(short *) value);
|
|
case NC_INT:
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
return getNCvx_int_int(ncp, varp, start, nelems,
|
|
(int *) value);
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
return getNCvx_int_long(ncp, varp, start, nelems,
|
|
(long *) value);
|
|
#else
|
|
#error "getNCvdata implementation"
|
|
#endif
|
|
case NC_FLOAT:
|
|
return getNCvx_float_float(ncp, varp, start, nelems,
|
|
(float *) value);
|
|
case NC_DOUBLE:
|
|
return getNCvx_double_double(ncp, varp, start, nelems,
|
|
(double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
/*
|
|
* output 'nelems' items of contiguous data of 'varp' at 'start'
|
|
* N.B. this function deprecated.
|
|
*/
|
|
static int
|
|
putNCvdata(NC *ncp, const NC_var *varp,
|
|
const size_t *start, size_t nelems, const void *value)
|
|
{
|
|
switch(varp->type){
|
|
case NC_CHAR:
|
|
return putNCvx_char_char(ncp, varp, start, nelems,
|
|
(const char *) value);
|
|
case NC_BYTE:
|
|
return putNCvx_schar_schar(ncp, varp, start, nelems,
|
|
(const schar *) value);
|
|
case NC_SHORT:
|
|
return putNCvx_short_short(ncp, varp, start, nelems,
|
|
(const short *) value);
|
|
case NC_INT:
|
|
#if (SIZEOF_INT >= X_SIZEOF_INT)
|
|
return putNCvx_int_int(ncp, varp, start, nelems,
|
|
(const int *) value);
|
|
#elif SIZEOF_LONG == X_SIZEOF_INT
|
|
return putNCvx_long_int(ncp, varp, start, nelems,
|
|
(const long *) value);
|
|
#else
|
|
#error "putNCvdata implementation"
|
|
#endif
|
|
case NC_FLOAT:
|
|
return putNCvx_float_float(ncp, varp, start, nelems,
|
|
(const float *) value);
|
|
case NC_DOUBLE:
|
|
return putNCvx_double_double(ncp, varp, start, nelems,
|
|
(const double *) value);
|
|
}
|
|
return NC_EBADTYPE;
|
|
}
|
|
|
|
|
|
static size_t
|
|
NCelemsPerRec(
|
|
const NC_var *varp)
|
|
{
|
|
size_t nelems = 1;
|
|
size_t jj;
|
|
for(jj = 1; jj < varp->ndims; jj++)
|
|
nelems *= varp->shape[jj];
|
|
return nelems;
|
|
}
|
|
|
|
|
|
/*
|
|
* Retrieves the number of record variables, the record variable ids, and the
|
|
* record size of each record variable. If any pointer to info to be returned
|
|
* is null, the associated information is not returned. Returns -1 on error.
|
|
*/
|
|
int
|
|
nc_inq_rec(
|
|
int ncid,
|
|
size_t *nrecvars,
|
|
int *recvarids,
|
|
size_t *recsizes)
|
|
{
|
|
NC *ncp;
|
|
|
|
{
|
|
const int status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
}
|
|
|
|
{
|
|
size_t nrvars = 0;
|
|
size_t ii = 0;
|
|
for(; ii < ncp->vars.nelems; ii++)
|
|
{
|
|
const NC_var *const varp = ncp->vars.value[ii];
|
|
if(!IS_RECVAR(varp))
|
|
continue;
|
|
|
|
if(recvarids != NULL)
|
|
recvarids[nrvars] = (int) ii;
|
|
if(recsizes != NULL)
|
|
{
|
|
*recsizes++ = nctypelen(varp->type)
|
|
* NCelemsPerRec(varp);
|
|
}
|
|
nrvars++;
|
|
}
|
|
|
|
if(nrecvars != NULL)
|
|
*nrecvars = nrvars;
|
|
}
|
|
|
|
return NC_NOERR;
|
|
}
|
|
|
|
|
|
static int
|
|
NCrecput(
|
|
NC *ncp,
|
|
size_t recnum,
|
|
void *const *datap)
|
|
{
|
|
int status = NC_NOERR;
|
|
size_t nrvars = 0;
|
|
NC_var *varp;
|
|
size_t ii;
|
|
size_t iocount;
|
|
ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems);
|
|
|
|
assert(ncp->dims.nelems != 0);
|
|
|
|
(void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t));
|
|
coord[0] = recnum;
|
|
for(ii = 0; ii < ncp->vars.nelems; ii++)
|
|
{
|
|
varp = ncp->vars.value[ii];
|
|
if(!IS_RECVAR(varp))
|
|
continue;
|
|
/* else */
|
|
nrvars++;
|
|
if(*datap == NULL)
|
|
{
|
|
datap++;
|
|
continue;
|
|
}
|
|
/* else */
|
|
iocount = NCelemsPerRec(varp);
|
|
status = putNCvdata(ncp, varp, coord, iocount, *datap++);
|
|
if(status != NC_NOERR)
|
|
break;
|
|
}
|
|
if(nrvars == 0 && status == NC_NOERR)
|
|
{
|
|
status = NC_ENORECVARS;
|
|
}
|
|
|
|
FREE_ONSTACK(coord);
|
|
return status;
|
|
}
|
|
|
|
|
|
static int
|
|
NCrecget(
|
|
NC *ncp,
|
|
size_t recnum,
|
|
void **datap)
|
|
{
|
|
int status = NC_NOERR;
|
|
size_t nrvars = 0;
|
|
NC_var *varp;
|
|
size_t ii;
|
|
size_t iocount;
|
|
ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems);
|
|
|
|
assert(ncp->dims.nelems != 0);
|
|
|
|
(void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t));
|
|
coord[0] = recnum;
|
|
for(ii = 0; ii < ncp->vars.nelems; ii++)
|
|
{
|
|
varp = ncp->vars.value[ii];
|
|
if(!IS_RECVAR(varp))
|
|
continue;
|
|
/* else */
|
|
nrvars++;
|
|
if(*datap == NULL)
|
|
{
|
|
datap++;
|
|
continue;
|
|
}
|
|
/* else */
|
|
iocount = NCelemsPerRec(varp);
|
|
status = getNCvdata(ncp, varp, coord, iocount, *datap++);
|
|
if(status != NC_NOERR)
|
|
break;
|
|
}
|
|
if(nrvars == 0 && status == NC_NOERR)
|
|
{
|
|
status = NC_ENORECVARS;
|
|
}
|
|
|
|
FREE_ONSTACK(coord);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Write one record's worth of data, except don't write to variables for which
|
|
* the address of the data to be written is null. Return -1 on error.
|
|
*/
|
|
int
|
|
nc_put_rec(
|
|
int ncid,
|
|
size_t recnum,
|
|
void * const *datap)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(ncp))
|
|
{
|
|
return NC_EPERM;
|
|
}
|
|
|
|
if(NC_indef(ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
status = NCvnrecs(ncp, recnum +1);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
return( NCrecput(ncp, recnum, datap) );
|
|
}
|
|
|
|
|
|
/*
|
|
* Read one record's worth of data, except don't read from variables for which
|
|
* the address of the data to be read is null. Return -1 on error;
|
|
*/
|
|
int
|
|
nc_get_rec(
|
|
int ncid,
|
|
size_t recnum,
|
|
void **datap)
|
|
{
|
|
int status;
|
|
NC *ncp;
|
|
|
|
status = NC_check_id(ncid, &ncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_indef(ncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
if(recnum >= ncp->numrecs)
|
|
{
|
|
return NC_EINVALCOORDS;
|
|
}
|
|
|
|
return( NCrecget(ncp, recnum, datap) );
|
|
}
|
|
|
|
|
|
/*
|
|
* Copy the values of a variable from an input netCDF to an output netCDF.
|
|
* Input and output var assummed to have the same shape.
|
|
* return -1 on error.
|
|
*/
|
|
int
|
|
nc_copy_var(int ncid_in, int varid, int ncid_out)
|
|
{
|
|
int status = NC_NOERR;
|
|
NC *inncp, *outncp;
|
|
NC_var *invp, *outvp;
|
|
|
|
status = NC_check_id(ncid_in, &inncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
|
|
if(NC_indef(inncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
status = NC_check_id(ncid_out, &outncp);
|
|
if(status != NC_NOERR)
|
|
return status;
|
|
|
|
if(NC_readonly(outncp))
|
|
{
|
|
/* output file isn't writable */
|
|
return NC_EPERM;
|
|
}
|
|
|
|
if(NC_indef(outncp))
|
|
{
|
|
return NC_EINDEFINE;
|
|
}
|
|
|
|
/* find the variable in the input cdf */
|
|
invp = NC_lookupvar(inncp, varid);
|
|
if(invp == NULL)
|
|
{
|
|
return NC_ENOTVAR;
|
|
}
|
|
|
|
/* find the variable in the output cdf */
|
|
if(NC_findvar(&outncp->vars, invp->name->cp, &outvp) == -1)
|
|
{
|
|
return NC_ENOTVAR;
|
|
}
|
|
|
|
/* can we even attempt to copy without conversion? */
|
|
if(outvp->type != invp->type)
|
|
{
|
|
return NC_EINVAL;
|
|
}
|
|
|
|
if( (invp->ndims == 0 && outvp->ndims != 0)
|
|
|| (invp->ndims != 0 && outvp->ndims == 0)
|
|
|| (IS_RECVAR(invp) && !IS_RECVAR(outvp))
|
|
|| (!IS_RECVAR(invp) && IS_RECVAR(outvp))
|
|
|| (invp->len != outvp->len)
|
|
)
|
|
{
|
|
return NC_EINVAL;
|
|
}
|
|
|
|
/*
|
|
* Check coordinates
|
|
*/
|
|
{
|
|
ALLOC_ONSTACK(coord, size_t, invp->ndims);
|
|
(void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t));
|
|
if(IS_RECVAR(invp))
|
|
*coord = inncp->numrecs;
|
|
|
|
{
|
|
size_t ii = 0;
|
|
for(; ii < invp->ndims; ii++)
|
|
coord[ii] --;
|
|
}
|
|
/* at this point, coord is the largest valid coord of invp */
|
|
|
|
if(NCcoordck(outncp, outvp, coord) != NC_NOERR)
|
|
{
|
|
return NC_EINVAL;
|
|
}
|
|
/* else */
|
|
|
|
(void) memset(coord, 0, invp->ndims * sizeof(size_t));
|
|
|
|
if(!IS_RECVAR(invp))
|
|
{
|
|
status = NCxvarcpy(inncp, invp, coord,
|
|
outncp, outvp, coord,
|
|
invp->len);
|
|
goto done;
|
|
}
|
|
/* else */
|
|
|
|
status = NCvnrecs(outncp, inncp->numrecs);
|
|
if(status != NC_NOERR)
|
|
goto done;
|
|
|
|
for( /*NADA*/; *coord < inncp->numrecs; (*coord)++)
|
|
{
|
|
status = NCxvarcpy(inncp, invp, coord,
|
|
outncp, outvp, coord,
|
|
invp->len);
|
|
if(status != NC_NOERR)
|
|
break;
|
|
}
|
|
done:
|
|
FREE_ONSTACK(coord);
|
|
}
|
|
return status;
|
|
}
|
|
|