/* Copyright 2018 University Corporation for Atmospheric Research/Unidata. See copyright file for more info. */ /** * @file * Functions to write attributes. * * These functions write attributes. */ #include "ncdispatch.h" /** * @name Writing Attributes * * Functions to write attributes. */ /** \{ */ /** * @ingroup attributes * Write a string attribute. * * The function nc_put_att_string adds or changes a variable attribute * or global attribute of an open netCDF dataset. The string type is * only available in netCDF-4/HDF5 files, when ::NC_CLASSIC_MODEL has * not been used in nc_create(). * * @param ncid NetCDF or group ID, from a previous call to nc_open(), * nc_create(), nc_def_grp(), or associated inquiry functions such as * nc_inq_ncid(). * * @param varid Variable ID of the variable to which the attribute * will be assigned or ::NC_GLOBAL for a global or group attribute. * * @param name Attribute \ref object_name. \ref attribute_conventions * may apply. * * @param len Number of values provided for the attribute. * * @param value Pointer to one or more values. * * @return ::NC_NOERR No error. * @return ::NC_EINVAL More than one value for _FillValue or trying to * set global _FillValue. * @return ::NC_ENOTVAR Couldn't find varid. * @return ::NC_EBADTYPE Fill value and var must be same type. * @return ::NC_ENOMEM Out of memory * @return ::NC_ELATEFILL Fill values must be written while the file * is still in initial define mode. * * @author Ed Hartnett, Dennis Heimbigner */ int nc_put_att_string(int ncid, int varid, const char *name, size_t len, const char** value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, NC_STRING, len, (void*)value, NC_STRING); } /** * @ingroup attributes * Write a text attribute. * * Add or change a text attribute. If this attribute is new, or if the * space required to store the attribute is greater than before, the * netCDF dataset must be in define mode for classic formats (or * netCDF-4/HDF5 with NC_CLASSIC_MODEL). * * Although it's possible to create attributes of all types, text and * double attributes are adequate for most purposes. * * Use the nc_put_att function to create attributes of any type, * including user-defined types. We recommend using the type safe * versions of this function whenever possible. * * @param ncid NetCDF or group ID, from a previous call to nc_open(), * nc_create(), nc_def_grp(), or associated inquiry functions such as * nc_inq_ncid(). * * @param varid Variable ID of the variable to which the attribute * will be assigned or ::NC_GLOBAL for a global attribute. * * @param name Attribute \ref object_name. \ref attribute_conventions * may apply. * * @param len Number of values provided for the attribute. * * @param value Pointer to one or more values. * * @return ::NC_NOERR No error. * @return ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue. * @return ::NC_ENOTVAR Couldn't find varid. * @return ::NC_EBADTYPE Fill value and var must be same type. * @return ::NC_ENOMEM Out of memory * @return ::NC_ELATEFILL Fill values must be written while the file * is still in initial define mode. * * @note With netCDF-4 files, nc_put_att will notice if you are * writing a _Fill_Value_ attribute, and will tell the HDF5 layer to * use the specified fill value for that variable. * * @section nc_put_att_text_example Example * * Here is an example using nc_put_att_double() to add a variable * attribute named valid_range for a netCDF variable named rh and * nc_put_att_text() to add a global attribute named title to an * existing netCDF dataset named foo.nc: * @code #include ... int status; int ncid; int rh_id; static double rh_range[] = {0.0, 100.0}; static char title[] = "example netCDF dataset"; ... status = nc_open("foo.nc", NC_WRITE, &ncid); if (status != NC_NOERR) handle_error(status); ... status = nc_redef(ncid); if (status != NC_NOERR) handle_error(status); status = nc_inq_varid (ncid, "rh", &rh_id); if (status != NC_NOERR) handle_error(status); ... status = nc_put_att_double (ncid, rh_id, "valid_range", NC_DOUBLE, 2, rh_range); if (status != NC_NOERR) handle_error(status); status = nc_put_att_text (ncid, NC_GLOBAL, "title", strlen(title), title) if (status != NC_NOERR) handle_error(status); ... status = nc_enddef(ncid); if (status != NC_NOERR) handle_error(status); @endcode */ int nc_put_att_text(int ncid, int varid, const char *name, size_t len, const char *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, NC_CHAR, len, (void *)value, NC_CHAR); } /** \} */ /** * @ingroup attributes * Write an attribute. * * The function nc_put_att_ type adds or changes a variable attribute * or global attribute of an open netCDF dataset. If this attribute is * new, or if the space required to store the attribute is greater * than before, the netCDF dataset must be in define mode for classic * formats (or netCDF-4/HDF5 with NC_CLASSIC_MODEL). * * With netCDF-4 files, nc_put_att will notice if you are writing a * _FillValue attribute, and will tell the HDF5 layer to use the * specified fill value for that variable. With either classic or * netCDF-4 files, a _FillValue attribute will be checked for * validity, to make sure it has only one value and that its type * matches the type of the associated variable. * * Although it's possible to create attributes of all types, text and * double attributes are adequate for most purposes. * * @param ncid NetCDF or group ID, from a previous call to nc_open(), * nc_create(), nc_def_grp(), or associated inquiry functions such as * nc_inq_ncid(). * * @param varid Variable ID of the variable to which the attribute will * be assigned or ::NC_GLOBAL for a global or group attribute. * * @param name Attribute \ref object_name. \ref attribute_conventions * may apply. * * @param xtype \ref data_type of the attribute. * * @param len Number of values provided for the attribute. * * @param value Pointer to one or more values. * * @return ::NC_NOERR No error. * @return ::NC_EINVAL More than one value for _FillValue or trying to * set global _FillValue. * @return ::NC_ENOTVAR Couldn't find varid. * @return ::NC_EBADTYPE Fill value and var must be same type. * @return ::NC_ENOMEM Out of memory * @return ::NC_ELATEFILL Fill values must be written while the file * is still in initial define mode. * * @section nc_put_att_double_example Example * * Here is an example using nc_put_att_double() to add a variable * attribute named valid_range for a netCDF variable named rh and * nc_put_att_text() to add a global attribute named title to an * existing netCDF dataset named foo.nc: * @code #include ... int status; int ncid; int rh_id; static double rh_range[] = {0.0, 100.0}; static char title[] = "example netCDF dataset"; ... status = nc_open("foo.nc", NC_WRITE, &ncid); if (status != NC_NOERR) handle_error(status); ... status = nc_redef(ncid); if (status != NC_NOERR) handle_error(status); status = nc_inq_varid (ncid, "rh", &rh_id); if (status != NC_NOERR) handle_error(status); ... status = nc_put_att_double (ncid, rh_id, "valid_range", NC_DOUBLE, 2, rh_range); if (status != NC_NOERR) handle_error(status); status = nc_put_att_text (ncid, NC_GLOBAL, "title", strlen(title), title) if (status != NC_NOERR) handle_error(status); ... status = nc_enddef(ncid); if (status != NC_NOERR) handle_error(status); @endcode */ /** \{*/ int nc_put_att(int ncid, int varid, const char *name, nc_type xtype, size_t len, const void *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, value, xtype); } int nc_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, size_t len, const signed char *value) { NC *ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_BYTE); } int nc_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype, size_t len, const unsigned char *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } int nc_put_att_short(int ncid, int varid, const char *name, nc_type xtype, size_t len, const short *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_SHORT); } int nc_put_att_int(int ncid, int varid, const char *name, nc_type xtype, size_t len, const int *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT); } int nc_put_att_long(int ncid, int varid, const char *name, nc_type xtype, size_t len, const long *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, longtype); } int nc_put_att_float(int ncid, int varid, const char *name, nc_type xtype, size_t len, const float *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_FLOAT); } int nc_put_att_double(int ncid, int varid, const char *name, nc_type xtype, size_t len, const double *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_DOUBLE); } int nc_put_att_ubyte(int ncid, int varid, const char *name, nc_type xtype, size_t len, const unsigned char *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UBYTE); } int nc_put_att_ushort(int ncid, int varid, const char *name, nc_type xtype, size_t len, const unsigned short *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_USHORT); } int nc_put_att_uint(int ncid, int varid, const char *name, nc_type xtype, size_t len, const unsigned int *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT); } int nc_put_att_longlong(int ncid, int varid, const char *name, nc_type xtype, size_t len, const long long *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_INT64); } int nc_put_att_ulonglong(int ncid, int varid, const char *name, nc_type xtype, size_t len, const unsigned long long *value) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; return ncp->dispatch->put_att(ncid, varid, name, xtype, len, (void *)value, NC_UINT64); }