mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
a clean commit for #383
This commit is contained in:
parent
0f7118107e
commit
0f4a85b9f2
@ -1302,6 +1302,11 @@ IF(SIZEOF_UINT)
|
||||
SET(HAVE_UINT TRUE)
|
||||
ENDIF(SIZEOF_UINT)
|
||||
|
||||
CHECK_TYPE_SIZE("schar" SIZEOF_SCHAR)
|
||||
IF(SIZEOF_SCHAR)
|
||||
SET(HAVE_SCHAR TRUE)
|
||||
ENDIF(SIZEOF_SCHAR)
|
||||
|
||||
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
|
||||
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
|
||||
IF(SIZEOF_LONG_LONG)
|
||||
|
@ -158,7 +158,8 @@ NC3_def_var(int ncid, const char *name,
|
||||
|
||||
extern int
|
||||
NC3_inq_var(int ncid, int varid, char *name,
|
||||
nc_type *xtypep, int *ndimsp, int *dimidsp, int *nattsp);
|
||||
nc_type *xtypep, int *ndimsp, int *dimidsp, int *nattsp,
|
||||
int *no_fill, void *fill_valuep);
|
||||
|
||||
extern int
|
||||
NC3_inq_varid(int ncid, const char *name, int *varidp);
|
||||
@ -166,6 +167,8 @@ NC3_inq_varid(int ncid, const char *name, int *varidp);
|
||||
extern int
|
||||
NC3_rename_var(int ncid, int varid, const char *name);
|
||||
|
||||
extern int
|
||||
NC3_def_var_fill(int,int,int,const void*);
|
||||
|
||||
extern int
|
||||
NC3_put_vara(int ncid, int varid,
|
||||
|
@ -186,6 +186,7 @@ typedef struct NC_var {
|
||||
nc_type type; /* the discriminant */
|
||||
size_t len; /* the total length originally allocated */
|
||||
off_t begin;
|
||||
int no_fill; /* whether fill mode is ON or OFF */
|
||||
} NC_var;
|
||||
|
||||
typedef struct NC_vararray {
|
||||
|
@ -9,7 +9,9 @@
|
||||
#ifndef _DISPATCH_H
|
||||
#define _DISPATCH_H
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -250,6 +252,7 @@ int (*inq_var_all)(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
);
|
||||
|
||||
int (*var_par_access)(int, int, int);
|
||||
int (*def_var_fill)(int, int, int, const void*);
|
||||
|
||||
/* Note the following may still be invoked by netcdf client code
|
||||
even when the file is a classic file; they will just return an error or
|
||||
@ -289,7 +292,6 @@ int (*def_opaque)(int, size_t, const char*, nc_type*);
|
||||
int (*def_var_deflate)(int, int, int, int, int);
|
||||
int (*def_var_fletcher32)(int, int, int);
|
||||
int (*def_var_chunking)(int, int, int, const size_t*);
|
||||
int (*def_var_fill)(int, int, int, const void*);
|
||||
int (*def_var_endian)(int, int, int);
|
||||
int (*def_var_filter)(int, int, unsigned int, size_t, const unsigned int*);
|
||||
int (*set_var_chunk_cache)(int, int, size_t, size_t, float);
|
||||
|
@ -137,6 +137,7 @@ NCDEFAULT_put_varm,
|
||||
NCD2_inq_var_all,
|
||||
|
||||
NCD2_var_par_access,
|
||||
NCD2_def_var_fill,
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
NCD2_show_metadata,
|
||||
@ -172,7 +173,6 @@ NCD2_def_opaque,
|
||||
NCD2_def_var_deflate,
|
||||
NCD2_def_var_fletcher32,
|
||||
NCD2_def_var_chunking,
|
||||
NCD2_def_var_fill,
|
||||
NCD2_def_var_endian,
|
||||
NCD2_def_var_filter,
|
||||
NCD2_set_var_chunk_cache,
|
||||
@ -2434,6 +2434,15 @@ NCD2_var_par_access(int ncid, int p2, int p3)
|
||||
return THROW(NC_ENOPAR);
|
||||
}
|
||||
|
||||
int
|
||||
NCD2_def_var_fill(int ncid, int p2, int p3, const void* p4)
|
||||
{
|
||||
NC* drno;
|
||||
int ret;
|
||||
if((ret = NC_check_id(ncid, (NC**)&drno)) != NC_NOERR) return THROW(ret);
|
||||
ret = nc_def_var_fill(getnc3id(drno), p2, p3, p4);
|
||||
return THROW(ret);
|
||||
}
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
|
||||
@ -2763,16 +2772,6 @@ NCD2_def_var_chunking(int ncid, int p2, int p3, const size_t* p4)
|
||||
return THROW(ret);
|
||||
}
|
||||
|
||||
int
|
||||
NCD2_def_var_fill(int ncid, int p2, int p3, const void* p4)
|
||||
{
|
||||
NC* drno;
|
||||
int ret;
|
||||
if((ret = NC_check_id(ncid, (NC**)&drno)) != NC_NOERR) return THROW(ret);
|
||||
ret = nc_def_var_fill(getnc3id(drno), p2, p3, p4);
|
||||
return THROW(ret);
|
||||
}
|
||||
|
||||
int
|
||||
NCD2_def_var_endian(int ncid, int p2, int p3)
|
||||
{
|
||||
|
@ -158,6 +158,9 @@ NCD2_rename_var(int ncid, int varid, const char *name);
|
||||
extern int
|
||||
NCD2_var_par_access(int, int, int);
|
||||
|
||||
extern int
|
||||
NCD2_def_var_fill(int, int, int, const void *);
|
||||
|
||||
/* netCDF4 API only */
|
||||
#ifdef USE_NETCDF4
|
||||
extern int
|
||||
@ -241,9 +244,6 @@ NCD2_var_par_access(int, int, int);
|
||||
extern int
|
||||
NCD2_def_var_chunking(int, int, int, const size_t *);
|
||||
|
||||
extern int
|
||||
NCD2_def_var_fill(int, int, int, const void *);
|
||||
|
||||
extern int
|
||||
NCD2_def_var_endian(int, int, int);
|
||||
|
||||
|
@ -853,6 +853,7 @@ NCDEFAULT_put_varm,
|
||||
NCD4_inq_var_all,
|
||||
|
||||
NCD4_var_par_access,
|
||||
NCD4_def_var_fill,
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
NCD4_show_metadata,
|
||||
@ -888,7 +889,6 @@ NCD4_def_opaque,
|
||||
NCD4_def_var_deflate,
|
||||
NCD4_def_var_fletcher32,
|
||||
NCD4_def_var_chunking,
|
||||
NCD4_def_var_fill,
|
||||
NCD4_def_var_endian,
|
||||
NCD4_def_var_filter,
|
||||
NCD4_set_var_chunk_cache,
|
||||
|
@ -538,6 +538,79 @@ NC_getshape(int ncid, int varid, int ndims, size_t* shape)
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! Set the fill value for a variable.
|
||||
|
||||
\ingroup variables
|
||||
|
||||
\param ncid NetCDF ID, from a previous call to nc_open or
|
||||
nc_create.
|
||||
|
||||
\param varid Variable ID.
|
||||
|
||||
\param no_fill Set to NC_NOFILL to turn off fill mode for this
|
||||
variable. Set to NC_FILL (the default) to turn on fill mode for the
|
||||
variable.
|
||||
|
||||
\param fill_value the fill value to be used for this variable. Must be
|
||||
the same type as the variable. This must point to enough free memory
|
||||
to hold one element of the data type of the variable. (For example, an
|
||||
NC_INT will require 4 bytes for it's fill value, which is also an
|
||||
NC_INT.)
|
||||
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ID.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode. This is returned for
|
||||
netCDF classic, 64-bit offset, or 64-bit data files, or for netCDF-4 files,
|
||||
when they were created with NC_STRICT_NC3 flag. See \ref nc_create.
|
||||
* @returns ::NC_EPERM Attempt to create object in read-only file.
|
||||
|
||||
\section nc_def_var_fill_example Example
|
||||
|
||||
In this example from libsrc4/tst_vars.c, a variable is defined, and
|
||||
the fill mode turned off. Then nc_inq_fill() is used to check that the
|
||||
setting is correct. Then some data are written to the variable. Since
|
||||
the data that are written do not cover the full extent of the
|
||||
variable, the missing values will just be random. If fill value mode
|
||||
was turned on, the missing values would get the fill value.
|
||||
|
||||
\code
|
||||
#define DIM7_LEN 2
|
||||
#define DIM7_NAME "dim_7_from_Indiana"
|
||||
#define VAR7_NAME "var_7_from_Idaho"
|
||||
#define NDIMS 1
|
||||
int dimids[NDIMS];
|
||||
size_t index[NDIMS];
|
||||
int varid;
|
||||
int no_fill;
|
||||
unsigned short ushort_data = 42, ushort_data_in, fill_value_in;
|
||||
|
||||
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
||||
if (nc_def_dim(ncid, DIM7_NAME, DIM7_LEN, &dimids[0])) ERR;
|
||||
if (nc_def_var(ncid, VAR7_NAME, NC_USHORT, NDIMS, dimids,
|
||||
&varid)) ERR;
|
||||
if (nc_def_var_fill(ncid, varid, 1, NULL)) ERR;
|
||||
|
||||
if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR;
|
||||
if (!no_fill) ERR;
|
||||
|
||||
index[0] = 1;
|
||||
if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR;
|
||||
|
||||
index[0] = 0;
|
||||
if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR;
|
||||
|
||||
if (nc_close(ncid)) ERR;
|
||||
\endcode
|
||||
*/
|
||||
int
|
||||
nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
NC* ncp;
|
||||
int stat = NC_check_id(ncid,&ncp);
|
||||
if(stat != NC_NOERR) return stat;
|
||||
return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
|
||||
}
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
/** \ingroup variables
|
||||
|
||||
@ -899,80 +972,6 @@ nc_def_var_chunking(int ncid, int varid, int storage,
|
||||
chunksizesp);
|
||||
}
|
||||
|
||||
/*! Set the fill value for a netCDF4/HDF5 variable.
|
||||
|
||||
\ingroup variables
|
||||
|
||||
\param ncid NetCDF ID, from a previous call to nc_open or
|
||||
nc_create.
|
||||
|
||||
\param varid Variable ID.
|
||||
|
||||
\param no_fill Set to NC_NOFILL to turn off fill mode for this
|
||||
variable. Set to NC_FILL (the default) to turn on fill mode for the
|
||||
variable.
|
||||
|
||||
\param fill_value the fill value to be used for this variable. Must be
|
||||
the same type as the variable. This must point to enough free memory
|
||||
to hold one element of the data type of the variable. (For example, an
|
||||
NC_INT will require 4 bytes for it's fill value, which is also an
|
||||
NC_INT.)
|
||||
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_EBADID Bad ID.
|
||||
* @returns ::NC_ENOTNC4 Not a netCDF-4 file.
|
||||
* @returns ::NC_ENOTINDEFINE Not in define mode. This is returned for
|
||||
netCDF classic or 64-bit offset files, or for netCDF-4 files, when
|
||||
they wwere created with NC_STRICT_NC3 flag. See \ref nc_create.
|
||||
* @returns ::NC_EPERM Attempt to create object in read-only file.
|
||||
|
||||
\section nc_def_var_fill_example Example
|
||||
|
||||
In this example from libsrc4/tst_vars.c, a variable is defined, and
|
||||
the fill mode turned off. Then nc_inq_fill() is used to check that the
|
||||
setting is correct. Then some data are written to the variable. Since
|
||||
the data that are written do not cover the full extent of the
|
||||
variable, the missing values will just be random. If fill value mode
|
||||
was turned on, the missing values would get the fill value.
|
||||
|
||||
\code
|
||||
#define DIM7_LEN 2
|
||||
#define DIM7_NAME "dim_7_from_Indiana"
|
||||
#define VAR7_NAME "var_7_from_Idaho"
|
||||
#define NDIMS 1
|
||||
int dimids[NDIMS];
|
||||
size_t index[NDIMS];
|
||||
int varid;
|
||||
int no_fill;
|
||||
unsigned short ushort_data = 42, ushort_data_in, fill_value_in;
|
||||
|
||||
if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
|
||||
if (nc_def_dim(ncid, DIM7_NAME, DIM7_LEN, &dimids[0])) ERR;
|
||||
if (nc_def_var(ncid, VAR7_NAME, NC_USHORT, NDIMS, dimids,
|
||||
&varid)) ERR;
|
||||
if (nc_def_var_fill(ncid, varid, 1, NULL)) ERR;
|
||||
|
||||
if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR;
|
||||
if (!no_fill) ERR;
|
||||
|
||||
index[0] = 1;
|
||||
if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR;
|
||||
|
||||
index[0] = 0;
|
||||
if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR;
|
||||
|
||||
if (nc_close(ncid)) ERR;
|
||||
\endcode
|
||||
*/
|
||||
int
|
||||
nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
NC* ncp;
|
||||
int stat = NC_check_id(ncid,&ncp);
|
||||
if(stat != NC_NOERR) return stat;
|
||||
return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ingroup variables
|
||||
|
||||
|
@ -836,6 +836,18 @@ NC3_put_att(
|
||||
if(nelems != 0 && value == NULL)
|
||||
return NC_EINVAL; /* Null arg */
|
||||
|
||||
if (varid != NC_GLOBAL && !strcmp(name, _FillValue)) {
|
||||
/* Fill value must be of the same data type */
|
||||
if (type != ncp->vars.value[varid]->type) return NC_EBADTYPE;
|
||||
|
||||
/* Fill value must have exactly one value */
|
||||
if (nelems != 1) return NC_EINVAL;
|
||||
|
||||
/* Only allow for variables defined in initial define mode */
|
||||
if (ncp->old != NULL && varid < ncp->old->vars.nelems)
|
||||
return NC_ELATEFILL; /* try put attribute for an old variable */
|
||||
}
|
||||
|
||||
attrpp = NC_findattr(ncap, name);
|
||||
|
||||
/* 4 cases: exists X indef */
|
||||
|
@ -73,7 +73,6 @@ static int NC3_def_opaque(int,size_t,const char*,nc_type*);
|
||||
static int NC3_def_var_deflate(int,int,int,int,int);
|
||||
static int NC3_def_var_fletcher32(int,int,int);
|
||||
static int NC3_def_var_chunking(int,int,int,const size_t*);
|
||||
static int NC3_def_var_fill(int,int,int,const void*);
|
||||
static int NC3_def_var_endian(int,int,int);
|
||||
static int NC3_def_var_filter(int, int, unsigned int, size_t, const unsigned int*);
|
||||
|
||||
@ -129,6 +128,7 @@ NCDEFAULT_put_varm,
|
||||
NC3_inq_var_all,
|
||||
|
||||
NC3_var_par_access,
|
||||
NC3_def_var_fill,
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
NC3_show_metadata,
|
||||
@ -164,7 +164,6 @@ NC3_def_opaque,
|
||||
NC3_def_var_deflate,
|
||||
NC3_def_var_fletcher32,
|
||||
NC3_def_var_chunking,
|
||||
NC3_def_var_fill,
|
||||
NC3_def_var_endian,
|
||||
NC3_def_var_filter,
|
||||
NC3_set_var_chunk_cache,
|
||||
@ -198,13 +197,12 @@ NC3_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
unsigned int* idp, size_t* nparamsp, unsigned int* params
|
||||
)
|
||||
{
|
||||
int stat = NC3_inq_var(ncid,varid,name,xtypep,ndimsp,dimidsp,nattsp);
|
||||
int stat = NC3_inq_var(ncid,varid,name,xtypep,ndimsp,dimidsp,nattsp,no_fill,fill_valuep);
|
||||
if(stat) return stat;
|
||||
if(shufflep) *shufflep = 0;
|
||||
if(deflatep) *deflatep = 0;
|
||||
if(fletcher32p) *fletcher32p = 0;
|
||||
if(contiguousp) *contiguousp = NC_CONTIGUOUS;
|
||||
if(no_fill) *no_fill = 1;
|
||||
if(endiannessp) return NC_ENOTNC4;
|
||||
if(idp) return NC_ENOTNC4;
|
||||
if(nparamsp) return NC_ENOTNC4;
|
||||
@ -506,12 +504,6 @@ NC3_def_var_chunking(int ncid, int varid, int contiguous, const size_t *chunksiz
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
static int
|
||||
NC3_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
static int
|
||||
NC3_def_var_endian(int ncid, int varid, int endianness)
|
||||
{
|
||||
|
@ -490,12 +490,13 @@ fillerup(NC3_INFO *ncp)
|
||||
NC_var **varpp;
|
||||
|
||||
assert(!NC_readonly(ncp));
|
||||
assert(NC_dofill(ncp));
|
||||
|
||||
/* loop thru vars */
|
||||
varpp = ncp->vars.value;
|
||||
for(ii = 0; ii < ncp->vars.nelems; ii++, varpp++)
|
||||
{
|
||||
if ((*varpp)->no_fill) continue;
|
||||
|
||||
if(IS_RECVAR(*varpp))
|
||||
{
|
||||
/* skip record variables */
|
||||
@ -538,6 +539,9 @@ fill_added_recs(NC3_INFO *gnu, NC3_INFO *old)
|
||||
for(; varid < (int)gnu->vars.nelems; varid++)
|
||||
{
|
||||
const NC_var *const gnu_varp = *(gnu_varpp + varid);
|
||||
|
||||
if (gnu_varp->no_fill) continue;
|
||||
|
||||
if(!IS_RECVAR(gnu_varp))
|
||||
{
|
||||
/* skip non-record variables */
|
||||
@ -566,6 +570,9 @@ fill_added(NC3_INFO *gnu, NC3_INFO *old)
|
||||
for(; varid < (int)gnu->vars.nelems; varid++)
|
||||
{
|
||||
const NC_var *const gnu_varp = *(gnu_varpp + varid);
|
||||
|
||||
if (gnu_varp->no_fill) continue;
|
||||
|
||||
if(IS_RECVAR(gnu_varp))
|
||||
{
|
||||
/* skip record variables */
|
||||
@ -840,7 +847,7 @@ NC_endef(NC3_INFO *ncp,
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
|
||||
if(NC_dofill(ncp))
|
||||
/* fill mode is now per variable */
|
||||
{
|
||||
if(NC_IsNew(ncp))
|
||||
{
|
||||
@ -1432,7 +1439,7 @@ int
|
||||
NC3_set_fill(int ncid,
|
||||
int fillmode, int *old_mode_ptr)
|
||||
{
|
||||
int status;
|
||||
int i, status;
|
||||
NC *nc;
|
||||
NC3_INFO* nc3;
|
||||
int oldmode;
|
||||
@ -1473,6 +1480,14 @@ NC3_set_fill(int ncid,
|
||||
if(old_mode_ptr != NULL)
|
||||
*old_mode_ptr = oldmode;
|
||||
|
||||
/* loop thru all variables to set/overwrite its fill mode */
|
||||
for (i=0; i<nc3->vars.nelems; i++)
|
||||
nc3->vars.value[i]->no_fill = (fillmode == NC_NOFILL);
|
||||
|
||||
/* once the file's fill mode is set, any new variables defined after
|
||||
* this call will check NC_dofill(nc3) and set their no_fill accordingly.
|
||||
* See NC3_def_var() */
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
|
76
libsrc/var.c
76
libsrc/var.c
@ -16,6 +16,7 @@
|
||||
#include "ncx.h"
|
||||
#include "rnd.h"
|
||||
#include "ncutf8.h"
|
||||
#include "nc3dispatch.h"
|
||||
|
||||
#ifndef OFF_T_MAX
|
||||
#if 0
|
||||
@ -637,6 +638,13 @@ NC3_def_var( int ncid, const char *name, nc_type type,
|
||||
|
||||
if(varidp != NULL)
|
||||
*varidp = (int)ncp->vars.nelems -1; /* varid */
|
||||
|
||||
/* set the variable's fill mode */
|
||||
if (NC_dofill(ncp))
|
||||
varp->no_fill = 0;
|
||||
else
|
||||
varp->no_fill = 1;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -673,7 +681,9 @@ NC3_inq_var(int ncid,
|
||||
nc_type *typep,
|
||||
int *ndimsp,
|
||||
int *dimids,
|
||||
int *nattsp)
|
||||
int *nattsp,
|
||||
int *no_fillp,
|
||||
void *fill_valuep)
|
||||
{
|
||||
int status;
|
||||
NC *nc;
|
||||
@ -714,6 +724,18 @@ NC3_inq_var(int ncid,
|
||||
*nattsp = (int) varp->attrs.nelems;
|
||||
}
|
||||
|
||||
if (no_fillp != NULL) *no_fillp = varp->no_fill;
|
||||
|
||||
if (fill_valuep != NULL) {
|
||||
status = nc_get_att(ncid, varid, _FillValue, fill_valuep);
|
||||
if (status != NC_NOERR && status != NC_ENOTATT)
|
||||
return status;
|
||||
if (status == NC_ENOTATT) {
|
||||
status = NC3_inq_default_fill_value(varp->type, fill_valuep);
|
||||
if (status != NC_NOERR) return status;
|
||||
}
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -799,3 +821,55 @@ NC3_rename_var(int ncid, int varid, const char *unewname)
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
int
|
||||
NC3_def_var_fill(int ncid,
|
||||
int varid,
|
||||
int no_fill,
|
||||
const void *fill_value)
|
||||
{
|
||||
int status;
|
||||
NC *nc;
|
||||
NC3_INFO* ncp;
|
||||
NC_var *varp;
|
||||
|
||||
status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
ncp = NC3_DATA(nc);
|
||||
|
||||
if(NC_readonly(ncp))
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
|
||||
if(!NC_indef(ncp))
|
||||
{
|
||||
return NC_ENOTINDEFINE;
|
||||
}
|
||||
|
||||
varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
|
||||
if(varp == NULL)
|
||||
return NC_ENOTVAR;
|
||||
|
||||
if (no_fill)
|
||||
varp->no_fill = 1;
|
||||
else
|
||||
varp->no_fill = 0;
|
||||
|
||||
/* Are we setting a fill value? */
|
||||
if (fill_value != NULL && !varp->no_fill) {
|
||||
|
||||
/* If there's a _FillValue attribute, delete it. */
|
||||
status = NC3_del_att(ncid, varid, _FillValue);
|
||||
if (status != NC_NOERR && status != NC_ENOTATT)
|
||||
return status;
|
||||
|
||||
/* Create/overwrite attribute _FillValue */
|
||||
status = NC3_put_att(ncid, varid, _FillValue, varp->type, 1, fill_value, varp->type);
|
||||
if (status != NC_NOERR) return status;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ NCDEFAULT_put_varm,
|
||||
NC4_inq_var_all,
|
||||
|
||||
NC4_var_par_access,
|
||||
NC4_def_var_fill,
|
||||
|
||||
NC4_show_metadata,
|
||||
NC4_inq_unlimdims,
|
||||
@ -92,7 +93,6 @@ NC4_def_opaque,
|
||||
NC4_def_var_deflate,
|
||||
NC4_def_var_fletcher32,
|
||||
NC4_def_var_chunking,
|
||||
NC4_def_var_fill,
|
||||
NC4_def_var_endian,
|
||||
NC4_def_var_filter,
|
||||
NC4_set_var_chunk_cache,
|
||||
|
@ -1171,7 +1171,7 @@ NCP_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
if(deflatep) *deflatep = 0;
|
||||
if(fletcher32p) *fletcher32p = 0;
|
||||
if(contiguousp) *contiguousp = NC_CONTIGUOUS;
|
||||
if(no_fill) *no_fill = 1;
|
||||
if(no_fill) ncmpi_inq_var_fill(nc->int_ncid, varid, no_fill, fill_valuep);
|
||||
if(endiannessp) return NC_ENOTNC4;
|
||||
if(idp) return NC_ENOTNC4;
|
||||
if(nparamsp) return NC_ENOTNC4;
|
||||
@ -1179,6 +1179,15 @@ NCP_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
static int
|
||||
NCP_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
NC* nc;
|
||||
int status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR) return status;
|
||||
return ncmpi_def_var_fill(nc->int_ncid, varid, no_fill, fill_value);
|
||||
}
|
||||
|
||||
static int
|
||||
NCP_var_par_access(int ncid, int varid, int par_access)
|
||||
{
|
||||
@ -1492,12 +1501,6 @@ NCP_def_var_chunking(int ncid, int varid, int contiguous, const size_t *chunksiz
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
static int
|
||||
NCP_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
|
||||
{
|
||||
return NC_ENOTNC4;
|
||||
}
|
||||
|
||||
static int
|
||||
NCP_def_var_endian(int ncid, int varid, int endianness)
|
||||
{
|
||||
@ -1563,6 +1566,7 @@ NCP_put_varm,
|
||||
NCP_inq_var_all,
|
||||
|
||||
NCP_var_par_access,
|
||||
NCP_def_var_fill,
|
||||
|
||||
#ifdef USE_NETCDF4
|
||||
NCP_show_metadata,
|
||||
@ -1599,7 +1603,6 @@ NCP_def_opaque,
|
||||
NCP_def_var_deflate,
|
||||
NCP_def_var_fletcher32,
|
||||
NCP_def_var_chunking,
|
||||
NCP_def_var_fill,
|
||||
NCP_def_var_endian,
|
||||
NCP_def_var_filter,
|
||||
NCP_set_var_chunk_cache,
|
||||
|
@ -30,7 +30,7 @@ TARGET_LINK_LIBRARIES(nc_test
|
||||
)
|
||||
|
||||
# Some extra stand-alone tests
|
||||
SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type tst_global_fillval)
|
||||
SET(TESTS t_nc tst_small tst_misc tst_norm tst_names tst_nofill tst_nofill2 tst_nofill3 tst_meta tst_inq_type tst_utf8_validate tst_utf8_phrases tst_global_fillval tst_max_var_dims tst_formats tst_def_var_fill)
|
||||
|
||||
IF(NOT HAVE_BASH)
|
||||
SET(TESTS ${TESTS} tst_atts3)
|
||||
|
@ -20,7 +20,7 @@ TEST_EXTENSIONS = .sh
|
||||
TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm tst_names \
|
||||
tst_nofill tst_nofill2 tst_nofill3 tst_atts3 tst_meta tst_inq_type \
|
||||
tst_utf8_validate tst_utf8_phrases tst_global_fillval \
|
||||
tst_max_var_dims tst_formats
|
||||
tst_max_var_dims tst_formats tst_def_var_fill
|
||||
|
||||
if USE_NETCDF4
|
||||
TESTPROGRAMS += tst_atts tst_put_vars tst_elatefill
|
||||
|
@ -2361,6 +2361,23 @@ ifdef(`PNETCDF', `
|
||||
ELSE_NOK
|
||||
}
|
||||
}
|
||||
|
||||
/* enter redef mode and add a new variable, check NC_ELATEFILL */
|
||||
err = APIFunc(redef)(ncid);
|
||||
IF (err != NC_NOERR)
|
||||
error("redef: %s", APIFunc(strerror)(err));
|
||||
|
||||
/* it is not allowed to define fill value when variable already exists */
|
||||
err = APIFunc(def_var_fill)(ncid, 0, 0, &value);
|
||||
IF (err != NC_ELATEFILL)
|
||||
error("redef: expect NC_ELATEFILL but got %s", nc_err_code_name(err));
|
||||
err = APIFunc(def_var)(ncid, "new_var", NC_INT, 0, NULL, &varid);
|
||||
IF (err != NC_NOERR)
|
||||
error("redef: %s", APIFunc(strerror)(err));
|
||||
err = APIFunc(def_var_fill)(ncid, varid, 0, &value);
|
||||
IF (err != NC_NOERR)
|
||||
error("def_var_fill: %s", APIFunc(strerror)(err));
|
||||
|
||||
err = APIFunc(close)(ncid);
|
||||
IF (err != NC_NOERR)
|
||||
error("close: %s", APIFunc(strerror)(err));
|
||||
|
122
nc_test/tst_def_var_fill.c
Normal file
122
nc_test/tst_def_var_fill.c
Normal file
@ -0,0 +1,122 @@
|
||||
/* This is part of the netCDF package.
|
||||
* Copyright 2005 University Corporation for Atmospheric Research/Unidata
|
||||
* See COPYRIGHT file for conditions of use.
|
||||
*
|
||||
* Test per-variable fill mode for classic file formats.
|
||||
*
|
||||
* Author: Wei-keng Liao.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h> /* basename() */
|
||||
#include <netcdf.h>
|
||||
|
||||
#define CHECK_ERR { \
|
||||
if (err != NC_NOERR) { \
|
||||
nerrs++; \
|
||||
printf("Error at line %d in %s: (%s)\n", \
|
||||
__LINE__,__FILE__,nc_strerror(err)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NY 8
|
||||
#define NX 5
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char filename[256];
|
||||
int i, j, err, nerrs=0, ncid, varid[2], dimid[2], *buf;
|
||||
size_t start[2], count[2];
|
||||
|
||||
if (argc > 2) {
|
||||
printf("Usage: %s [filename]\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (argc == 2) snprintf(filename, 256, "%s", argv[1]);
|
||||
else strcpy(filename, "testfile.nc");
|
||||
|
||||
char *cmd_str = (char*)malloc(strlen(argv[0]) + 256);
|
||||
sprintf(cmd_str, "*** TESTING C %s for def_var_fill ", basename(argv[0]));
|
||||
printf("%-66s ------ ", cmd_str); fflush(stdout);
|
||||
free(cmd_str);
|
||||
|
||||
/* create a new file for writing ----------------------------------------*/
|
||||
err = nc_create(filename, NC_CLOBBER, &ncid); CHECK_ERR
|
||||
|
||||
/* define dimension */
|
||||
err = nc_def_dim(ncid, "Y", NY, &dimid[0]); CHECK_ERR
|
||||
err = nc_def_dim(ncid, "X", NX, &dimid[1]); CHECK_ERR
|
||||
|
||||
/* define variables */
|
||||
err = nc_def_var(ncid, "var_nofill", NC_INT, 2, dimid, &varid[0]); CHECK_ERR
|
||||
err = nc_def_var(ncid, "var_fill", NC_INT, 2, dimid, &varid[1]); CHECK_ERR
|
||||
|
||||
/* set fill mode for variables */
|
||||
err = nc_def_var_fill(ncid, varid[0], 1, NULL); CHECK_ERR
|
||||
err = nc_def_var_fill(ncid, varid[1], 0, NULL); CHECK_ERR
|
||||
|
||||
err = nc_enddef(ncid); CHECK_ERR
|
||||
|
||||
/* write a subarray to both variables */
|
||||
buf = (int*) malloc(NY*NX * sizeof(int));
|
||||
for (i=0; i<NY*NX; i++) buf[i] = 5;
|
||||
start[0] = 0;
|
||||
start[1] = 2;
|
||||
count[0] = NY;
|
||||
count[1] = 2;
|
||||
err = nc_put_vara_int(ncid, varid[0], start, count, buf); CHECK_ERR
|
||||
err = nc_put_vara_int(ncid, varid[1], start, count, buf); CHECK_ERR
|
||||
err = nc_close(ncid); CHECK_ERR
|
||||
|
||||
/* Now, reopen the file and read variables back */
|
||||
err = nc_open(filename, NC_WRITE, &ncid); CHECK_ERR
|
||||
|
||||
/* get variable IDs */
|
||||
err = nc_inq_varid(ncid, "var_nofill", &varid[0]); CHECK_ERR
|
||||
err = nc_inq_varid(ncid, "var_fill", &varid[1]); CHECK_ERR
|
||||
|
||||
/* read variable "var_nofill" and check contents */
|
||||
for (i=0; i<NY*NX; i++) buf[i] = -1;
|
||||
err = nc_get_var_int(ncid, varid[0], buf); CHECK_ERR
|
||||
for (i=0; i<NY; i++) {
|
||||
for (j=0; j<NX; j++) {
|
||||
if (2 <= j && j < 4) {
|
||||
if (buf[i*NX+j] != 5) {
|
||||
printf("Error at line %d in %s: expect get buf[%d]=%d but got %d\n",
|
||||
__LINE__,__FILE__,i*NX+j, 5, buf[i*NX+j]);
|
||||
nerrs++;
|
||||
}
|
||||
}
|
||||
else if (buf[i*NX+j] == NC_FILL_INT) {
|
||||
printf("Warning at line %d in %s: get buf[%d] same as NC_FILL_INT\n",
|
||||
__LINE__,__FILE__,i*NX+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* read variable "var_fill" and check contents */
|
||||
for (i=0; i<NY*NX; i++) buf[i] = -1;
|
||||
err = nc_get_var_int(ncid, varid[1], buf); CHECK_ERR
|
||||
for (i=0; i<NY; i++) {
|
||||
for (j=0; j<NX; j++) {
|
||||
int expect = NC_FILL_INT;
|
||||
if (2 <= j && j< 4) expect = 5;
|
||||
|
||||
if (buf[i*NX+j] != expect) {
|
||||
printf("Error at line %d in %s: expect get buf[%d]=%d but got %d\n",
|
||||
__LINE__,__FILE__,i*NX+j, expect, buf[i*NX+j]);
|
||||
nerrs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = nc_close(ncid); CHECK_ERR
|
||||
free(buf);
|
||||
|
||||
if (nerrs) printf("fail with %d mismatches\n",nerrs);
|
||||
else printf("pass\n");
|
||||
|
||||
return (nerrs > 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user