diff --git a/.travis.yml b/.travis.yml index 240cb48193..3dc594ff66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,4 +37,4 @@ before_install: script: - - docker run --rm -it -h "$CURHOST" -e USEDASH=FALSE -e RUNF=OFF -e RUNCXX=OFF -e RUNP=OFF -e RUNNCO=OFF -e USECMAKE=$USECMAKE -e USEAC=$USEAC -e DISTCHECK=$DISTCHECK -e COPTS="$COPTS" -e AC_OPTS="$AC_OPTS" -e CTEST_OUTPUT_ON_FAILURE=1 -v $(pwd):/netcdf-c -e USE_LOCAL_CP=$USECP -e TESTPROC=100 -e ENABLE_FILTER_TESTING=$TESTFILTER $DOCKIMG + - docker run --privileged --rm -it -h "$CURHOST" -e USEDASH=FALSE -e RUNF=OFF -e RUNCXX=OFF -e RUNP=OFF -e RUNNCO=OFF -e USECMAKE=$USECMAKE -e USEAC=$USEAC -e DISTCHECK=$DISTCHECK -e COPTS="$COPTS" -e AC_OPTS="$AC_OPTS" -e CTEST_OUTPUT_ON_FAILURE=1 -v $(pwd):/netcdf-c -e USE_LOCAL_CP=$USECP -e TESTPROC=100 -e ENABLE_FILTER_TESTING=$TESTFILTER -e ENABLE_C_MEMCHECK=OFF $DOCKIMG diff --git a/CMakeLists.txt b/CMakeLists.txt index c998aa54f7..4d79f4fd68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,13 +26,13 @@ set(PACKAGE "netCDF" CACHE STRING "") SET(NC_VERSION_MAJOR 4) SET(NC_VERSION_MINOR 6) -SET(NC_VERSION_PATCH 3) +SET(NC_VERSION_PATCH 4) SET(NC_VERSION_NOTE "-development") SET(netCDF_VERSION ${NC_VERSION_MAJOR}.${NC_VERSION_MINOR}.${NC_VERSION_PATCH}${NC_VERSION_NOTE}) SET(VERSION ${netCDF_VERSION}) SET(NC_VERSION ${netCDF_VERSION}) -SET(netCDF_LIB_VERSION 13) -SET(netCDF_SO_VERSION 13) +SET(netCDF_LIB_VERSION 15) +SET(netCDF_SO_VERSION 15) SET(PACKAGE_VERSION ${VERSION}) # Get system configuration, Use it to determine osname, os release, cpu. These @@ -737,6 +737,8 @@ IF(USE_HDF5 OR ENABLE_NETCDF_4) CHECK_LIBRARY_EXISTS(${HDF5_C_LIBRARY_hdf5} H5Pset_libver_bounds "" HDF5_HAS_LIBVER_BOUNDS) CHECK_LIBRARY_EXISTS(${HDF5_C_LIBRARY_hdf5} H5free_memory "" HDF5_HAS_H5FREE) + CHECK_LIBRARY_EXISTS(${HDF5_C_LIBRARY_hdf5} H5allocate_memory "" HDF5_HAS_ALLOCATE_MEMORY) + CHECK_LIBRARY_EXISTS(${HDF5_C_LIBRARY_hdf5} H5resize_memory "" HDF5_HAS_RESIZE_MEMORY) IF(HDF5_PARALLEL) SET(HDF5_CC h5pcc) @@ -1845,7 +1847,7 @@ FOREACH(_LIB ${ALL_TLL_LIBS}) LIST(APPEND LINKFLAGS "-L${_LIB_DIR}") ENDFOREACH() -SET(NC_LIBS "-lnetcdf ${NC_LIBS}") +#SET(NC_LIBS "-lnetcdf ${NC_LIBS}") STRING(REPLACE ";" " " NC_LIBS "${NC_LIBS}") STRING(REPLACE "-lhdf5::hdf5-shared" "-lhdf5" NC_LIBS ${NC_LIBS}) @@ -1859,6 +1861,9 @@ STRING(REPLACE ";" " " LINKFLAGS "${LINKFLAGS}") LIST(REMOVE_DUPLICATES NC_LIBS) LIST(REMOVE_DUPLICATES LINKFLAGS) +SET(LIBS ${NC_LIBS}) +SET(NC_LIBS "-lnetcdf") + configure_file( ${netCDF_SOURCE_DIR}/netcdf.pc.in ${netCDF_BINARY_DIR}/netcdf.pc @ONLY) @@ -1919,10 +1924,6 @@ SET(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS_${CMAKE_BU is_disabled(BUILD_SHARED_LIBS enable_static) is_enabled(BUILD_SHARED_LIBS enable_shared) -# Remove libnetcdf from NC_LIBS. -STRING(REPLACE "-lnetcdf " "" TMP_NC_LIBS "${NC_LIBS}") -SET(LIBS "${TMP_NC_LIBS}") - is_enabled(ENABLE_V2_API HAS_NC2) is_enabled(ENABLE_NETCDF_4 HAS_NC4) is_enabled(ENABLE_HDF4 HAS_HDF4) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8a7310609a..4151186d37 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,15 +5,16 @@ Release Notes {#RELEASE_NOTES} This file contains a high-level description of this package's evolution. Releases are in reverse chronological order (most recent first). Note that, as of netcdf 4.2, the `netcdf-c++` and `netcdf-fortran` libraries have been separated into their own libraries. -## 4.6.3 - TBD - -## 4.6.2.1 - February 15, 2019 - -### Maintenance Release +## 4.6.3 - February 28, 2019 +* [Bug Fix] Correctly generated `netcdf.pc` generated either by `configure` or `cmake`. If linking against a static netcdf, you would need to pass the `--static` argument to `pkg-config` in order to list all of the downstream dependencies. See [Github #1324](https://github.com/Unidata/netcdf-c/issues/1324) for more information. +* Now always write hidden coordinates attribute, which allows faster file opens when present. See [Github #1262](https://github.com/Unidata/netcdf-c/issues/1262) for more information. +* Some fixes for rename, including fix for renumbering of varids after a rename (#1307), renaming var to dim without coordinate var. See [Github #1297](https://github.com/Unidata/netcdf-c/issues/1297). +* Fix of NULL parameter causing segfaults in put_vars functions. See [Github #1265](https://github.com/Unidata/netcdf-c/issues/1265) for more information. +* Fix of --enable-benchmark benchmark tests [Github #1211](https://github.com/Unidata/netcdf-c/issues/1211) * Update the license from the home-brewed NetCDF license to the standard 3-Clause BSD License. This change does not result in any new restrictions; it is merely the adoption of a standard, well-known and well-understood license in place of the historic NetCDF license written at Unidata. This is part of a broader push by Unidata to adopt modern, standardized licensing. * [BugFix] Corrected DAP-releated issues on big-endian machines. See [Github #1321](https://github.com/Unidata/netcdf-c/issues/1321), [Github #1302](https://github.com/Unidata/netcdf-c/issues/1302) for more information. -* [BugFix][Enhancement] Various and sundry bugfixes and performance enhancements, thanks to @edhartnett, @gsjaardema, @t-b, @wkliao, and all of our other contributors. +* [BugFix][Enhancement] Various and sundry bugfixes and performance enhancements, thanks to \@edhartnett, \@gsjaardema, \@t-b, \@wkliao, and all of our other contributors. * [Enhancement] Extended `nccopy -F` syntax to support multiple variables with a single invocation. See [Github #1311](https://github.com/Unidata/netcdf-c/issues/1311) for more information. * [BugFix] Corrected an issue where DAP2 was incorrectly converting signed bytes, resulting in an erroneous error message under some circumstances. See [GitHub #1317](https://github.com/Unidata/netcdf-c/issues/1317) for more information. See [Github #1319](https://github.com/Unidata/netcdf-c/issues/1319) for related information. * [BugFix][Enhancement] Modified `nccopy` so that `_NCProperties` is not copied over verbatim but is instead generated based on the version of `libnetcdf` used when copying the file. Additionally, `_NCProperties` are displayed if/when associated with a netcdf3 file, now. See [GitHub #803](https://github.com/Unidata/netcdf-c/issues/803) for more information. diff --git a/config.h.cmake.in b/config.h.cmake.in index 9c145fb135..7fbbc26a68 100644 --- a/config.h.cmake.in +++ b/config.h.cmake.in @@ -367,6 +367,12 @@ are set when opening a binary file on Windows. */ nc4file. */ #cmakedefine HDF5_HAS_H5FREE 1 +/* if true, H5allocate_memory() will be used. */ +#cmakedefine HDF5_HAS_ALLOCATE_MEMORY 1 + +/* if true, H5resize_memory() will be used. */ +#cmakedefine HDF5_HAS_RESIZE_MEMORY 1 + /* if true, hdf5 has parallelism enabled */ #cmakedefine HDF5_PARALLEL 1 diff --git a/configure.ac b/configure.ac index 828d5501fd..b5543fbf61 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ AC_PREREQ([2.59]) # Initialize with name, version, and support email address. -AC_INIT([netCDF], [4.6.3-development], [support-netcdf@unidata.ucar.edu], [netcdf-c]) +AC_INIT([netCDF], [4.6.4-development], [support-netcdf@unidata.ucar.edu], [netcdf-c]) ## # Prefer an empty CFLAGS variable instead of the default -g -O2. @@ -24,7 +24,7 @@ AC_INIT([netCDF], [4.6.3-development], [support-netcdf@unidata.ucar.edu], [netcd AC_SUBST([NC_VERSION_MAJOR]) NC_VERSION_MAJOR=4 AC_SUBST([NC_VERSION_MINOR]) NC_VERSION_MINOR=6 -AC_SUBST([NC_VERSION_PATCH]) NC_VERSION_PATCH=3 +AC_SUBST([NC_VERSION_PATCH]) NC_VERSION_PATCH=4 AC_SUBST([NC_VERSION_NOTE]) NC_VERSION_NOTE="-development" ##### @@ -1028,7 +1028,7 @@ if test "x$enable_hdf5" = xyes; then # H5Pset_fapl_mpiposix and H5Pget_fapl_mpiposix have been removed since HDF5 1.8.12. # Use H5Pset_fapl_mpio and H5Pget_fapl_mpio, instead. - AC_CHECK_FUNCS([H5Pget_fapl_mpio H5Pset_deflate H5Z_SZIP H5free_memory H5Pset_libver_bounds H5Pset_all_coll_metadata_ops]) + AC_CHECK_FUNCS([H5Pget_fapl_mpio H5Pset_deflate H5Z_SZIP H5free_memory H5resize_memory H5allocate_memory H5Pset_libver_bounds H5Pset_all_coll_metadata_ops]) # Check to see if HDF5 library has collective metadata APIs, (HDF5 >= 1.10.0) if test "x$ac_cv_func_H5Pset_all_coll_metadata_ops" = xyes; then @@ -1062,6 +1062,14 @@ if test "x$enable_hdf5" = xyes; then AC_DEFINE([HDF5_HAS_H5FREE], [1], [if true, H5free_memory() will be used to free hdf5-allocated memory in nc4file.]) fi + if test "x$ac_cv_func_H5allocate_memory" = xyes; then + AC_DEFINE([HDF5_HAS_ALLOCATE_MEMORY], [1], [if true, H5allocate_memory() will be used.]) + fi + + if test "x$ac_cv_func_H5resize_memory" = xyes; then + AC_DEFINE([HDF5_HAS_resize_MEMORY], [1], [if true, H5resize_memory() will be used.]) + fi + if test "x$ac_cv_func_H5Pset_libver_bounds" = xyes; then AC_DEFINE([HDF5_HAS_LIBVER_BOUNDS], [1], [if true, netcdf4 file properties will be set using H5Pset_libver_bounds]) fi diff --git a/docs/Doxyfile.developer b/docs/Doxyfile.developer index 84ef2c1106..c5ced7e021 100644 --- a/docs/Doxyfile.developer +++ b/docs/Doxyfile.developer @@ -38,7 +38,7 @@ PROJECT_NAME = netCDF-C # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.6.3-development +PROJECT_NUMBER = 4.6.4-development # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/docs/guide.dox b/docs/guide.dox index a581454f99..18ae59d96c 100644 --- a/docs/guide.dox +++ b/docs/guide.dox @@ -8,7 +8,6 @@ - \subpage netcdf_data_set_components - \subpage netcdf_perf_chunking - \subpage netcdf_utilities_guide -- \subpage compress - \subpage BestPractices - \subpage user_defined_formats - \subpage users_guide_appendices @@ -48,7 +47,10 @@ web site (http://www.unidata.ucar.edu/netcdf), and with the netCDF distribution. The latest version of this document, and the language specific guides, -can be found at the netCDF web site (http://www.unidata.ucar.edu/netcdf/docs) along with extensive additional information about netCDF, including pointers to other software that works with netCDF data. +can be found at the netCDF web site +(http://www.unidata.ucar.edu/netcdf/docs) along with extensive +additional information about netCDF, including pointers to other +software that works with netCDF data. Separate documentation of the Java netCDF library can be found at http://www.unidata.ucar.edu/software/netcdf-java/. @@ -88,8 +90,10 @@ were written. Unidata supports the netCDF interfaces for C (see NetCDF-C User's -Guide), Fortran (see NetCDF-Fortran User's Guide) -and C++ (see ), Fortran (see NetCDF-Fortran User's Guide) and C++ (see NetCDF C++ Interface Guide). The netCDF library is supported for various UNIX operating systems. A diff --git a/libdispatch/ddim.c b/libdispatch/ddim.c index 4abcc4e382..58b6fcda06 100644 --- a/libdispatch/ddim.c +++ b/libdispatch/ddim.c @@ -1,125 +1,122 @@ -/** \file -Dimension functions +/* Copyright 2018 University Corporation for Atmospheric + Research/Unidata. See COPYRIGHT file for more info. */ +/** + @file -These functions define and inquire about dimensions. - -Copyright 2018 University Corporation for Atmospheric -Research/Unidata. See COPYRIGHT file for more info. + The functions in this file define, inquire about, and rename + dimensions. */ #include "ncdispatch.h" -/*! \defgroup dimensions Dimensions - -Dimensions are used to define the shape of data in netCDF. - -Dimensions for a netCDF dataset are defined when it is created, while -the netCDF dataset is in define mode. Additional dimensions may be -added later by reentering define mode. A netCDF dimension has a name -and a length. In a netCDF classic or 64-bit offset file, at most one -dimension can have the unlimited length, which means variables using -this dimension can grow along this dimension. In a netCDF-4 file -multiple unlimited dimensions are supported. - -There is a suggested limit (1024) to the number of dimensions that can -be defined in a single netCDF dataset. The limit is the value of the -predefined macro NC_MAX_DIMS. The purpose of the limit is to make -writing generic applications simpler. They need only provide an array -of NC_MAX_DIMS dimensions to handle any netCDF dataset. The -implementation of the netCDF library does not enforce this advisory -maximum, so it is possible to use more dimensions, if necessary, but -netCDF utilities that assume the advisory maximums may not be able to -handle the resulting netCDF datasets. - -NC_MAX_VAR_DIMS, which must not exceed NC_MAX_DIMS, is the maximum -number of dimensions that can be used to specify the shape of a single -variable. It is also intended to simplify writing generic -applications. - -Ordinarily, the name and length of a dimension are fixed when the -dimension is first defined. The name may be changed later, but the -length of a dimension (other than the unlimited dimension) cannot be -changed without copying all the data to a new netCDF dataset with a -redefined dimension length. - -Dimension lengths in the C interface are type size_t rather than type -int to make it possible to access all the data in a netCDF dataset on -a platform that only supports a 16-bit int data type, for example -MSDOS. If dimension lengths were type int instead, it would not be -possible to access data from variables with a dimension length greater -than a 16-bit int can accommodate. - -A netCDF dimension in an open netCDF dataset is referred to by a small -integer called a dimension ID. In the C interface, dimension IDs are -0, 1, 2, ..., in the order in which the dimensions were defined. - -Operations supported on dimensions are: -- Create a dimension, given its name and length. -- Get a dimension ID from its name. -- Get a dimension's name and length from its ID. -- Rename a dimension. - +/** + @defgroup dimensions Dimensions + + Dimensions are used to define the shape of data in netCDF. + + Dimensions for a netCDF dataset are defined when it is created, + while the netCDF dataset is in define mode. Additional dimensions + may be added later by reentering define mode. A netCDF dimension + has a name and a length. In a netCDF classic or 64-bit offset file, + at most one dimension can have the unlimited length, which means + variables using this dimension can grow along this dimension. In a + netCDF-4 file multiple unlimited dimensions are supported. + + There is a suggested limit (1024) to the number of dimensions that + can be defined in a single netCDF dataset. The limit is the value + of the predefined macro ::NC_MAX_DIMS. The purpose of the limit is + to make writing generic applications simpler. They need only + provide an array of ::NC_MAX_DIMS dimensions to handle any netCDF + dataset. The implementation of the netCDF library does not enforce + this advisory maximum, so it is possible to use more dimensions, if + necessary, but netCDF utilities that assume the advisory maximums + may not be able to handle the resulting netCDF datasets. + + ::NC_MAX_VAR_DIMS, which must not exceed ::NC_MAX_DIMS, is the + maximum number of dimensions that can be used to specify the shape + of a single variable. It is also intended to simplify writing + generic applications. + + Ordinarily, the name and length of a dimension are fixed when the + dimension is first defined. The name may be changed later, but the + length of a dimension (other than the unlimited dimension) cannot + be changed without copying all the data to a new netCDF dataset + with a redefined dimension length. + + Dimension lengths in the C interface are type size_t rather than + type int to make it possible to access all the data in a netCDF + dataset on a platform that only supports a 16-bit int data type, + for example MSDOS. If dimension lengths were type int instead, it + would not be possible to access data from variables with a + dimension length greater than a 16-bit int can accommodate. + + A netCDF dimension in an open netCDF dataset is referred to by a + small integer called a dimension ID. In the C interface, dimension + IDs are 0, 1, 2, ..., in the order in which the dimensions were + defined. + + Operations supported on dimensions are: + - Create a dimension, given its name and length. + - Get a dimension ID from its name. + - Get a dimension's name and length from its ID. + - Rename a dimension. */ -/*! \{*/ /* All these functions are part of the above defgroup... */ - -/** \name Deleting and Renaming Dimensions - -Functions to delete or rename an dimension. */ -/*! \{ */ /* All these functions are part of this named group... */ - -/*! - -Define a new dimension. The function nc_def_dim adds a new -dimension to an open netCDF dataset in define mode. It returns (as an -argument) a dimension ID, given the netCDF ID, the dimension name, and -the dimension length. At most one unlimited length dimension, called -the record dimension, may be defined for each classic or 64-bit offset -netCDF dataset. NetCDF-4 datasets may have multiple unlimited -dimensions. - -\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 name Name of the dimension to be created. - -\param len Length of the dimension to be created. Use NC_UNLIMITED for -unlimited dimensions. - -\param idp Pointer where dimension ID will be stored. - -\retval ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_ENOTINDEFINE Not in define mode. -\returns ::NC_EDIMSIZE Invalid dimension size. -\returns ::NC_EUNLIMIT NC_UNLIMITED size already in use -\returns ::NC_EMAXDIMS NC_MAX_DIMS exceeded [not enforced after 4.5.0] -\returns ::NC_ENAMEINUSE String match to name in use -\returns ::NC_ENOMEM Memory allocation (malloc) failure -\returns ::NC_EPERM Write to read only - -\section nc_def_dim_example Example - -Here is an example using nc_def_dim() to create a dimension named lat of -length 18 and a unlimited dimension named rec in a new netCDF dataset -named foo.nc: - -\code - #include - ... - int status, ncid, latid, recid; - ... - status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); - if (status != NC_NOERR) handle_error(status); - ... - status = nc_def_dim(ncid, "lat", 18L, &latid); - if (status != NC_NOERR) handle_error(status); - status = nc_def_dim(ncid, "rec", NC_UNLIMITED, &recid); - if (status != NC_NOERR) handle_error(status); -\endcode - - */ +/** @{ */ + +/** + Define a new dimension. The function nc_def_dim() adds a new + dimension to an open netCDF dataset in define mode. It returns (as an + argument) a dimension ID, given the netCDF ID, the dimension name, and + the dimension length. At most one unlimited length dimension, called + the record dimension, may be defined for each classic or 64-bit offset + netCDF dataset. NetCDF-4 datasets may have multiple unlimited + dimensions. + + @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 name Name of the dimension to be created. + @param len Length of the dimension to be created. Use NC_UNLIMITED for + unlimited dimensions. + @param idp Pointer where dimension ID will be stored. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EMAXNAME Name is too long. + @return ::NC_EBADNAME Name breaks netCDF name rules. + @return ::NC_EINVAL Invalid input. + @return ::NC_ENOTINDEFINE Not in define mode. + @return ::NC_EDIMSIZE Invalid dimension size. + @return ::NC_EUNLIMIT NC_UNLIMITED size already in use + @return ::NC_EMAXDIMS NC_MAX_DIMS exceeded [not enforced after 4.5.0] + @return ::NC_ENAMEINUSE String match to name in use + @return ::NC_ENOMEM Memory allocation (malloc) failure + @return ::NC_EPERM Write to read only + + @section nc_def_dim_example Example + + Here is an example using nc_def_dim() to create a dimension named lat of + length 18 and a unlimited dimension named rec in a new netCDF dataset + named foo.nc: + + @code + #include + ... + int status, ncid, latid, recid; + ... + status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); + if (status != NC_NOERR) handle_error(status); + ... + status = nc_def_dim(ncid, "lat", 18L, &latid); + if (status != NC_NOERR) handle_error(status); + status = nc_def_dim(ncid, "rec", NC_UNLIMITED, &recid); + if (status != NC_NOERR) handle_error(status); + @endcode + + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_def_dim(int ncid, const char *name, size_t len, int *idp) { @@ -130,26 +127,27 @@ nc_def_dim(int ncid, const char *name, size_t len, int *idp) return ncp->dispatch->def_dim(ncid, name, len, idp); } -/*! -Find the ID of a dimension from the name. - -The function nc_inq_dimid returns (as an argument) the ID of a netCDF -dimension, given the name of the dimension. If ndims is the number of -dimensions defined for a netCDF dataset, each dimension has an ID -between 0 and ndims-1. +/** + Find the ID of a dimension from the name. -\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(). + The function nc_inq_dimid returns (as an argument) the ID of a + netCDF dimension, given the name of the dimension. If ndims is the + number of dimensions defined for a netCDF dataset, each dimension + has an ID between 0 and ndims-1. -\param name Name of the dimension. + @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 name Name of the dimension. + @param idp Pointer where dimension ID will be stored. -\param idp Pointer where dimension ID will be stored. + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EBADDIM Invalid dimension ID. -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_EBADDIM Invalid dimension ID or name. - */ + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_dimid(int ncid, const char *name, int *idp) { @@ -160,60 +158,60 @@ nc_inq_dimid(int ncid, const char *name, int *idp) return ncp->dispatch->inq_dimid(ncid,name,idp); } -/*! -Find the name and length of a dimension. - -The length for the unlimited dimension, if any, is the number of -records written so far. - -\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 dimid Dimension ID, from a previous call to nc_inq_dimid() or -nc_def_dim(). - -\param name Returned dimension name. The caller must allocate space -for the returned name. The maximum possible length, in characters, of -a dimension name is given by the predefined constant -NC_MAX_NAME. (This doesn't include the null terminator, so declare -your array to be size NC_MAX_NAME+1). The returned character array -will be null-terminated. - -\param lenp Pointer to location for returned length of dimension. For -the unlimited dimension, this is the number of records written so far. - -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_EBADDIM Invalid dimension ID or name. - -\section nc_inq_dim_example Example - -Here is an example using nc_inq_dim() to determine the length of a -dimension named lat, and the name and current maximum length of the -unlimited dimension for an existing netCDF dataset named foo.nc: - -\code - #include - ... - int status, ncid, latid, recid; - size_t latlength, recs; - char recname[NC_MAX_NAME+1]; - ... - status = nc_open("foo.nc", NC_NOWRITE, &ncid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_unlimdim(ncid, &recid); - if (status != NC_NOERR) handle_error(status); - ... - status = nc_inq_dimid(ncid, "lat", &latid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_dimlen(ncid, latid, &latlength); - if (status != NC_NOERR) handle_error(status); - - status = nc_inq_dim(ncid, recid, recname, &recs); - if (status != NC_NOERR) handle_error(status); -\endcode - */ +/** + Find the name and length of a dimension. + + The length for the unlimited dimension, if any, is the number of + records written so far. + + @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 dimid Dimension ID, from a previous call to nc_inq_dimid() or + nc_def_dim(). + @param name Returned dimension name. The caller must allocate space + for the returned name. The maximum possible length, in characters, of + a dimension name is given by the predefined constant + ::NC_MAX_NAME. (This doesn't include the null terminator, so declare + your array to be size NC_MAX_NAME+1). The returned character array + will be null-terminated. + @param lenp Pointer to location for returned length of dimension. For + the unlimited dimension, this is the number of records written so far. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EBADDIM Invalid dimension ID or name. + + @section nc_inq_dim_example Example + + Here is an example using nc_inq_dim() to determine the length of a + dimension named lat, and the name and current maximum length of the + unlimited dimension for an existing netCDF dataset named foo.nc: + + @code + #include + ... + int status, ncid, latid, recid; + size_t latlength, recs; + char recname[NC_MAX_NAME+1]; + ... + status = nc_open("foo.nc", NC_NOWRITE, &ncid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_unlimdim(ncid, &recid); + if (status != NC_NOERR) handle_error(status); + ... + status = nc_inq_dimid(ncid, "lat", &latid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_dimlen(ncid, latid, &latlength); + if (status != NC_NOERR) handle_error(status); + + status = nc_inq_dim(ncid, recid, recname, &recs); + if (status != NC_NOERR) handle_error(status); + @endcode + + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_dim(int ncid, int dimid, char *name, size_t *lenp) { @@ -224,59 +222,65 @@ nc_inq_dim(int ncid, int dimid, char *name, size_t *lenp) return ncp->dispatch->inq_dim(ncid,dimid,name,lenp); } -/*! -Rename a dimension. - -This function renames an existing dimension in a netCDF dataset open -for writing. You cannot rename a dimension to have the same name as -another dimension. - -For netCDF classic and 64-bit offset files, if the new name is longer -than the old name, the netCDF dataset must be in define mode. - -For netCDF-4 files the dataset is switched to define mode for the -rename, regardless of the name length. - -\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 dimid Dimension ID, from a previous call to nc_inq_dimid() or -nc_def_dim(). - -\param name New name for dimension. Must be a null-terminated string -with length less than NC_MAX_NAME. - -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_EBADDIM Invalid dimension ID or name. -\returns ::NC_ENAMEINUSE String match to name in use -\returns ::NC_ENOMEM Memory allocation (malloc) failure -\returns ::NC_EPERM Write to read only -\returns ::NC_ENOTINDEFINE Not in define mode and new name is longer than old. -\section nc_rename_dim_example Example - -Here is an example using nc_rename_dim to rename the dimension lat to -latitude in an existing netCDF dataset named foo.nc: - -\code - #include - ... - int status, ncid, latid; - ... - 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_dimid(ncid, "lat", &latid); - if (status != NC_NOERR) handle_error(status); - status = nc_rename_dim(ncid, latid, "latitude"); - if (status != NC_NOERR) handle_error(status); - status = nc_enddef(ncid); - if (status != NC_NOERR) handle_error(status); -\endcode - */ +/** + Rename a dimension. + + This function renames an existing dimension in a netCDF dataset + open for writing. You cannot rename a dimension to have the same + name as another dimension. + + For netCDF classic and 64-bit offset files, if the new name is + longer than the old name, which has been flushed to disk, the + netCDF dataset must be in define mode. + + For netCDF-4 files the length of the name is not checked against + the length of the old name, even for classic model files. This is + due to the difficulty of exactly reproducing classic library + behavior in this case. + + @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 dimid Dimension ID, from a previous call to nc_inq_dimid() + or nc_def_dim(). + @param name New name for dimension. Must be a null-terminated + string with length less than ::NC_MAX_NAME. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EBADDIM Invalid dimension ID or name. + @return ::NC_ENAMEINUSE String match to name in use + @return ::NC_ENOMEM Memory allocation (malloc) failure + @return ::NC_EPERM Write to read only + @return ::NC_ENOTINDEFINE Not in define mode and new name is longer + than old. + + @section nc_rename_dim_example Example + + Here is an example using nc_rename_dim to rename the dimension lat + to latitude in an existing netCDF dataset named foo.nc: + + @code + #include + ... + int status, ncid, latid; + ... + 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_dimid(ncid, "lat", &latid); + if (status != NC_NOERR) handle_error(status); + status = nc_rename_dim(ncid, latid, "latitude"); + if (status != NC_NOERR) handle_error(status); + status = nc_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + @endcode + + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_rename_dim(int ncid, int dimid, const char *name) { @@ -287,27 +291,28 @@ nc_rename_dim(int ncid, int dimid, const char *name) return ncp->dispatch->rename_dim(ncid,dimid,name); } -/*! -Find the number of dimensions. +/** + Find the number of dimensions. -In a classic model netCDF file, this function returns the number of -defined dimensions. In a netCDF-4/HDF5 file, this function returns the -number of dimensions available in the group specified by ncid, which -may be less than the total number of dimensions in a file. In a -netCDF-4/HDF5 file, dimensions are in all sub-groups, sub-sub-groups, -etc. + In a classic model netCDF file, this function returns the number of + defined dimensions. In a netCDF-4/HDF5 file, this function returns + the number of dimensions available in the group specified by ncid, + which may be less than the total number of dimensions in a file. In + a netCDF-4/HDF5 file, dimensions are in all sub-groups, + sub-sub-groups, etc. -\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 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 ndimsp Pointer where number of dimensions will be + written. Ignored if NULL. -\param ndimsp Pointer where number of dimensions will be -written. Ignored if NULL. + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. - - */ + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_ndims(int ncid, int *ndimsp) { @@ -319,26 +324,28 @@ nc_inq_ndims(int ncid, int *ndimsp) return ncp->dispatch->inq(ncid,ndimsp,NULL,NULL,NULL); } -/*! -Find the ID of the unlimited dimension. +/** + Find the ID of the unlimited dimension. -This function finds the ID of the unlimited dimension. For -netCDF-4/HDF5 files (which may have more than one unlimited -dimension), the ID of the first unlimited dimesnion is returned. For -these files, nc_inq_unlimdims() will return all the unlimited dimension IDs. + This function finds the ID of the unlimited dimension. For + netCDF-4/HDF5 files (which may have more than one unlimited + dimension), the ID of the first unlimited dimesnion is + returned. For these files, nc_inq_unlimdims() will return all the + unlimited dimension IDs. -\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 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 unlimdimidp Pointer where unlimited dimension ID will be + stored. If there is no unlimited dimension, -1 will be stored + here. Ignored if NULL. -\param unlimdimidp Pointer where unlimited dimension ID will be -stored. If there is no unlimited dimension, -1 will be stored -here. Ignored if NULL. + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. - - */ + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_unlimdim(int ncid, int *unlimdimidp) { @@ -349,55 +356,55 @@ nc_inq_unlimdim(int ncid, int *unlimdimidp) return ncp->dispatch->inq_unlimdim(ncid,unlimdimidp); } -/*! -Find out the name of a dimension. - -\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 dimid Dimension ID, from a previous call to nc_inq_dimid() or -nc_def_dim(). - -\param name Returned dimension name. The caller must allocate space -for the returned name. The maximum possible length, in characters, of -a dimension name is given by the predefined constant -NC_MAX_NAME. (This doesn't include the null terminator, so declare -your array to be size NC_MAX_NAME+1). The returned character array -will be null-terminated. Ignored if NULL. - -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_EBADDIM Invalid dimension ID or name. - -\section nc_inq_dim_example2 Example - -Here is an example using nc_inq_dim() to determine the length of a -dimension named lat, and the name and current maximum length of the -unlimited dimension for an existing netCDF dataset named foo.nc: - -\code - #include - ... - int status, ncid, latid, recid; - size_t latlength, recs; - char recname[NC_MAX_NAME+1]; - ... - status = nc_open("foo.nc", NC_NOWRITE, &ncid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_unlimdim(ncid, &recid); - if (status != NC_NOERR) handle_error(status); - ... - status = nc_inq_dimid(ncid, "lat", &latid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_dimlen(ncid, latid, &latlength); - if (status != NC_NOERR) handle_error(status); - - status = nc_inq_dim(ncid, recid, recname, &recs); - if (status != NC_NOERR) handle_error(status); -\endcode - - */ +/** + Find out the name of a dimension. + + @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 dimid Dimension ID, from a previous call to nc_inq_dimid() + or nc_def_dim(). + @param name Returned dimension name. The caller must allocate space + for the returned name. The maximum possible length, in characters, + of a dimension name is given by the predefined constant + ::NC_MAX_NAME. (This doesn't include the null terminator, so + declare your array to be size NC_MAX_NAME+1). The returned + character array will be null-terminated. Ignored if NULL. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EBADDIM Invalid dimension ID or name. + + @section nc_inq_dim_example2 Example + + Here is an example using nc_inq_dim() to determine the length of a + dimension named lat, and the name and current maximum length of the + unlimited dimension for an existing netCDF dataset named foo.nc: + + @code + #include + ... + int status, ncid, latid, recid; + size_t latlength, recs; + char recname[NC_MAX_NAME+1]; + ... + status = nc_open("foo.nc", NC_NOWRITE, &ncid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_unlimdim(ncid, &recid); + if (status != NC_NOERR) handle_error(status); + ... + status = nc_inq_dimid(ncid, "lat", &latid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_dimlen(ncid, latid, &latlength); + if (status != NC_NOERR) handle_error(status); + + status = nc_inq_dim(ncid, recid, recname, &recs); + if (status != NC_NOERR) handle_error(status); + @endcode + + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_dimname(int ncid, int dimid, char *name) { @@ -409,52 +416,53 @@ nc_inq_dimname(int ncid, int dimid, char *name) return ncp->dispatch->inq_dim(ncid,dimid,name,NULL); } -/*! -Find the length of a dimension. - -The length for the unlimited dimension, if any, is the number of -records written so far. - -\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 dimid Dimension ID, from a previous call to nc_inq_dimid() or -nc_def_dim(). - -\param lenp Pointer where the length will be stored. - -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Not a valid ID. -\returns ::NC_EBADDIM Invalid dimension ID or name. - -\section nc_inq_dim_example3 Example - -Here is an example using nc_inq_dim() to determine the length of a -dimension named lat, and the name and current maximum length of the -unlimited dimension for an existing netCDF dataset named foo.nc: - -\code - #include - ... - int status, ncid, latid, recid; - size_t latlength, recs; - char recname[NC_MAX_NAME+1]; - ... - status = nc_open("foo.nc", NC_NOWRITE, &ncid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_unlimdim(ncid, &recid); - if (status != NC_NOERR) handle_error(status); - ... - status = nc_inq_dimid(ncid, "lat", &latid); - if (status != NC_NOERR) handle_error(status); - status = nc_inq_dimlen(ncid, latid, &latlength); - if (status != NC_NOERR) handle_error(status); - - status = nc_inq_dim(ncid, recid, recname, &recs); - if (status != NC_NOERR) handle_error(status); -\endcode - */ +/** + Find the length of a dimension. + + The length for the unlimited dimension, if any, is the number of + records written so far. + + @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 dimid Dimension ID, from a previous call to nc_inq_dimid() + or nc_def_dim(). + @param lenp Pointer where the length will be stored. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Not a valid ID. + @return ::NC_EBADDIM Invalid dimension ID or name. + + @section nc_inq_dim_example3 Example + + Here is an example using nc_inq_dim() to determine the length of a + dimension named lat, and the name and current maximum length of the + unlimited dimension for an existing netCDF dataset named foo.nc: + + @code + #include + ... + int status, ncid, latid, recid; + size_t latlength, recs; + char recname[NC_MAX_NAME+1]; + ... + status = nc_open("foo.nc", NC_NOWRITE, &ncid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_unlimdim(ncid, &recid); + if (status != NC_NOERR) handle_error(status); + ... + status = nc_inq_dimid(ncid, "lat", &latid); + if (status != NC_NOERR) handle_error(status); + status = nc_inq_dimlen(ncid, latid, &latlength); + if (status != NC_NOERR) handle_error(status); + + status = nc_inq_dim(ncid, recid, recname, &recs); + if (status != NC_NOERR) handle_error(status); + @endcode + + @author Glenn Davis, Russ Rew, Ed Hartnett, Dennis Heimbigner, Ward + Fisher +*/ int nc_inq_dimlen(int ncid, int dimid, size_t *lenp) { @@ -466,6 +474,4 @@ nc_inq_dimlen(int ncid, int dimid, size_t *lenp) return ncp->dispatch->inq_dim(ncid,dimid,NULL,lenp); } -/*! \} */ /* End of named group ...*/ - -/*! \} */ /* End of defgroup. */ +/** @} */ diff --git a/libdispatch/dvar.c b/libdispatch/dvar.c index f91e5df315..07b0a62b8b 100644 --- a/libdispatch/dvar.c +++ b/libdispatch/dvar.c @@ -2,1190 +2,1211 @@ Research/Unidata. See COPYRIGHT file for more info. */ /** * @file - * Functions for defining and inquiring about variables. -*/ + * Functions for defining and inquiring about variables. @note The + * order of functions in this file affects the doxygen documentation. + */ #include "ncdispatch.h" #include "netcdf_f.h" /** -\defgroup variables Variables - -Variables hold multi-dimensional arrays of data. - -Variables for a netCDF dataset are defined when the dataset is -created, while the netCDF dataset is in define mode. Other variables -may be added later by reentering define mode. A netCDF variable has a -name, a type, and a shape, which are specified when it is defined. A -variable may also have values, which are established later in data -mode. - -Ordinarily, the name, type, and shape are fixed when the variable is -first defined. The name may be changed, but the type and shape of a -variable cannot be changed. However, a variable defined in terms of -the unlimited dimension can grow without bound in that dimension. - -A netCDF variable in an open netCDF dataset is referred to by a small -integer called a variable ID. - -Variable IDs reflect the order in which variables were defined within -a netCDF dataset. Variable IDs are 0, 1, 2,..., in the order in which -the variables were defined. A function is available for getting the -variable ID from the variable name and vice-versa. - -Attributes (see Attributes) may be associated with a variable to -specify such properties as units. - -Operations supported on variables are: -- Create a variable, given its name, data type, and shape. -- Get a variable ID from its name. -- Get a variable's name, data type, shape, and number of attributes - from its ID. -- Put a data value into a variable, given variable ID, indices, and value. -- Put an array of values into a variable, given variable ID, corner - indices, edge lengths, and a block of values. -- Put a subsampled or mapped array-section of values into a variable, - given variable ID, corner indices, edge lengths, stride vector, - index mapping vector, and a block of values. -- Get a data value from a variable, given variable ID and indices. -- Get an array of values from a variable, given variable ID, corner - indices, and edge lengths. -- Get a subsampled or mapped array-section of values from a variable, - given variable ID, corner indices, edge lengths, stride vector, and - index mapping vector. -- Rename a variable. - -\section language_types Language Types Corresponding to netCDF -External Data Types - -NetCDF supported six atomic data types through version 3.6.0 (char, -byte, short, int, float, and double). Starting with version 4.0, many -new atomic and user defined data types are supported (unsigned int -types, strings, compound types, variable length arrays, enums, -opaque). - -The additional data types are only supported in netCDF-4/HDF5 -files. To create netCDF-4/HDF5 files, use the HDF5 flag in -nc_create. (see nc_create). - -\section classic_types NetCDF-3 Classic and 64-Bit Offset Data Types - -NetCDF-3 classic and 64-bit offset files support 6 atomic data types, -and none of the user defined datatype introduced in NetCDF-4. - -The following table gives the netCDF-3 external data types and the -corresponding type constants for defining variables in the C -interface: - - - - - - - - - -
TypeC defineBits
byteNC_BYTE8
charNC_CHAR8
shortNC_SHORT16
intNC_INT32
floatNC_FLOAT32
doubleNC_DOUBLE64
- -The first column gives the netCDF external data type, which is the -same as the CDL data type. The next column gives the corresponding C -pre-processor macro for use in netCDF functions (the pre-processor -macros are defined in the netCDF C header-file netcdf.h). The last -column gives the number of bits used in the external representation of -values of the corresponding type. - -\section netcdf_4_atomic NetCDF-4 Atomic Types - -NetCDF-4 files support all of the atomic data types from netCDF-3, -plus additional unsigned integer types, 64-bit integer types, and a -string type. - - - - - - - - - - - - - - -
TypeC defineBits - -
byteNC_BYTE8
unsigned byte NC_UBYTE^ 8
char NC_CHAR 8
short NC_SHORT 16
unsigned short NC_USHORT^ 16
int NC_INT 32
unsigned int NC_UINT^ 32
unsigned long long NC_UINT64^ 64
long long NC_INT64^ 64
float NC_FLOAT 32
double NC_DOUBLE 64
char ** NC_STRING^ string length + 1
- -^This type was introduced in netCDF-4, and is not supported in netCDF -classic or 64-bit offset format files, or in netCDF-4 files if they -are created with the NC_CLASSIC_MODEL flags. - */ + @defgroup variables Variables + + Variables hold multi-dimensional arrays of data. + + Variables for a netCDF dataset are defined when the dataset is + created, while the netCDF dataset is in define mode. Other + variables may be added later by reentering define mode. A netCDF + variable has a name, a type, and a shape, which are specified when + it is defined. A variable may also have values, which are + established later in data mode. + + Ordinarily, the name, type, and shape are fixed when the variable + is first defined. The name may be changed, but the type and shape + of a variable cannot be changed. However, a variable defined in + terms of the unlimited dimension can grow without bound in that + dimension. + + A netCDF variable in an open netCDF dataset is referred to by a + small integer called a variable ID. + + Variable IDs reflect the order in which variables were defined + within a netCDF dataset. Variable IDs are 0, 1, 2,..., in the order + in which the variables were defined. A function is available for + getting the variable ID from the variable name and vice-versa. + + @ref attributes may be associated with a variable to specify such + properties as units. + + Operations supported on variables are: + - Create a variable, given its name, data type, and shape. + - Get a variable ID from its name. + - Get a variable's name, data type, shape, and number of attributes + from its ID. + - Put a data value into a variable, given variable ID, indices, and value. + - Put an array of values into a variable, given variable ID, corner + indices, edge lengths, and a block of values. + - Put a subsampled or mapped array-section of values into a variable, + given variable ID, corner indices, edge lengths, stride vector, + index mapping vector, and a block of values. + - Get a data value from a variable, given variable ID and indices. + - Get an array of values from a variable, given variable ID, corner + indices, and edge lengths. + - Get a subsampled or mapped array-section of values from a variable, + given variable ID, corner indices, edge lengths, stride vector, and + index mapping vector. + - Rename a variable. + + @section language_types Data Types + + NetCDF supported six atomic data types through version 3.6.0 (char, + byte, short, int, float, and double). Starting with version 4.0, many + new atomic and user defined data types are supported (unsigned int + types, strings, compound types, variable length arrays, enums, + opaque). + + The additional data types are only supported in netCDF-4/HDF5 + files. To create netCDF-4/HDF5 files, use the ::NC_NETCDF4 flag in + nc_create(). + + @section classic_types NetCDF-3 Classic and 64-Bit Offset Data Types + + NetCDF-3 classic and 64-bit offset files support 6 atomic data types, + and none of the user defined datatype introduced in NetCDF-4. + + The following table gives the netCDF-3 external data types and the + corresponding type constants for defining variables in the C + interface: + + + + + + + + + +
TypeC defineBits
byte::NC_BYTE8
char::NC_CHAR8
short::NC_SHORT16
int::NC_INT32
float::NC_FLOAT32
double::NC_DOUBLE64
+ + The first column gives the netCDF external data type, which is the + same as the CDL data type. The next column gives the corresponding C + pre-processor macro for use in netCDF functions (the pre-processor + macros are defined in the netCDF C header-file netcdf.h). The last + column gives the number of bits used in the external representation of + values of the corresponding type. + + @section netcdf_4_atomic NetCDF-4 Atomic Data Types + + NetCDF-4 files support all of the atomic data types from netCDF-3, + plus additional unsigned integer types, 64-bit integer types, and a + string type. + + + + + + + + + + + + + + +
TypeC defineBits + +
byte::NC_BYTE8
unsigned byte ::NC_UBYTE^ 8
char ::NC_CHAR 8
short ::NC_SHORT 16
unsigned short ::NC_USHORT^ 16
int ::NC_INT 32
unsigned int ::NC_UINT^ 32
unsigned long long ::NC_UINT64^ 64
long long ::NC_INT64^ 64
float ::NC_FLOAT 32
double ::NC_DOUBLE 64
char ** ::NC_STRING^ string length + 1
+ + ^This type was introduced in netCDF-4, and is not supported in netCDF + classic or 64-bit offset format files, or in netCDF-4 files if they + are created with the ::NC_CLASSIC_MODEL flags. +*/ +/** @{ */ /** -@name Defining Variables + @name Defining Variables -Use these functions to define variables. - */ -/*! \{ */ + Use these functions to define variables. +*/ +/*! @{ */ /** -@ingroup variables -Define a new variable. - -This function adds a new variable to an open netCDF dataset or group. -It returns (as an argument) a variable ID, given the netCDF ID, -the variable name, the variable type, the number of dimensions, and a -list of the dimension IDs. - -@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 name Variable \ref object_name. - -@param xtype \ref data_type of the variable. - -@param ndims Number of dimensions for the variable. For example, 2 -specifies a matrix, 1 specifies a vector, and 0 means the variable is -a scalar with no dimensions. Must not be negative or greater than the -predefined constant ::NC_MAX_VAR_DIMS. In netCDF-4/HDF5 files, may not -exceed the HDF5 maximum number of dimensions (32). - -@param dimidsp Vector of ndims dimension IDs corresponding to the -variable dimensions. For classic model netCDF files, if the ID of the -unlimited dimension is included, it must be first. This argument is -ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there -may be any number of unlimited dimensions, and they may be used in any -element of the dimids array. - -@param varidp Pointer to location for the returned variable ID. - -@returns ::NC_NOERR No error. -@returns ::NC_EBADID Bad ncid. -@returns ::NC_ENOTINDEFINE Not in define mode. -@returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file. -@returns ::NC_EMAXVARS NC_MAX_VARS exceeded [Not enforced after 4.5.0] -@returns ::NC_EBADTYPE Bad type. -@returns ::NC_EINVAL Invalid input. -@returns ::NC_ENAMEINUSE Name already in use. -@returns ::NC_EPERM Attempt to create object in read-only file. - -@section nc_def_var_example Example - -Here is an example using nc_def_var to create a variable named rh of -type double with three dimensions, time, lat, and lon in a new netCDF -dataset named foo.nc: - -@code - #include - ... - int status; - int ncid; - int lat_dim, lon_dim, time_dim; - int rh_id; - int rh_dimids[3]; - ... - status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); - if (status != NC_NOERR) handle_error(status); - ... - - status = nc_def_dim(ncid, "lat", 5L, &lat_dim); - if (status != NC_NOERR) handle_error(status); - status = nc_def_dim(ncid, "lon", 10L, &lon_dim); - if (status != NC_NOERR) handle_error(status); - status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim); - if (status != NC_NOERR) handle_error(status); - ... - - rh_dimids[0] = time_dim; - rh_dimids[1] = lat_dim; - rh_dimids[2] = lon_dim; - status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id); - if (status != NC_NOERR) handle_error(status); -@endcode -@author Glenn Davis, Ed Hartnett, Dennis Heimbigner - */ -int -nc_def_var(int ncid, const char *name, nc_type xtype, - int ndims, const int *dimidsp, int *varidp) -{ - NC* ncp; - int stat = NC_NOERR; - - if ((stat = NC_check_id(ncid, &ncp))) - return stat; - TRACE(nc_def_var); - return ncp->dispatch->def_var(ncid, name, xtype, ndims, - dimidsp, varidp); -} -/*! \} */ + Define a new variable. + + This function adds a new variable to an open netCDF dataset or group. + It returns (as an argument) a variable ID, given the netCDF ID, + the variable name, the variable type, the number of dimensions, and a + list of the dimension IDs. + + @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 name Variable @ref object_name. + @param xtype @ref data_type of the variable. + @param ndims Number of dimensions for the variable. For example, 2 + specifies a matrix, 1 specifies a vector, and 0 means the variable is + a scalar with no dimensions. Must not be negative or greater than the + predefined constant ::NC_MAX_VAR_DIMS. In netCDF-4/HDF5 files, may not + exceed the HDF5 maximum number of dimensions (32). + @param dimidsp Vector of ndims dimension IDs corresponding to the + variable dimensions. For classic model netCDF files, if the ID of the + unlimited dimension is included, it must be first. This argument is + ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there + may be any number of unlimited dimensions, and they may be used in any + element of the dimids array. + @param varidp Pointer to location for the returned variable ID. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTINDEFINE Not in define mode. + @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file. + @return ::NC_EMAXVARS NC_MAX_VARS exceeded [Not enforced after 4.5.0] + @return ::NC_EBADTYPE Bad type. + @return ::NC_EINVAL Invalid input. + @return ::NC_ENAMEINUSE Name already in use. + @return ::NC_EPERM Attempt to create object in read-only file. + + @section nc_def_var_example Example + + Here is an example using nc_def_var to create a variable named rh of + type double with three dimensions, time, lat, and lon in a new netCDF + dataset named foo.nc: + + @code + #include + ... + int status; + int ncid; + int lat_dim, lon_dim, time_dim; + int rh_id; + int rh_dimids[3]; + ... + status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); + if (status != NC_NOERR) handle_error(status); + ... -/** -@name Rename a Variable + status = nc_def_dim(ncid, "lat", 5L, &lat_dim); + if (status != NC_NOERR) handle_error(status); + status = nc_def_dim(ncid, "lon", 10L, &lon_dim); + if (status != NC_NOERR) handle_error(status); + status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim); + if (status != NC_NOERR) handle_error(status); + ... -Rename a variable. - */ -/*! \{ */ + rh_dimids[0] = time_dim; + rh_dimids[1] = lat_dim; + rh_dimids[2] = lon_dim; + status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id); + if (status != NC_NOERR) handle_error(status); + @endcode -/** -Rename a variable. -@ingroup variables - -This function changes the name of a netCDF variable in an open netCDF -file or group. You cannot rename a variable to have the name of any existing -variable. - -For classic format, 64-bit offset format, and netCDF-4/HDF5 with -classic mode, if the new name is longer than the old name, the netCDF -dataset must be in define mode. - -For netCDF-4/HDF5 files, renaming the variable changes the order of -the variables in the file. The renamed variable becomes the last -variable in the file. - -@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 - -@param name New name of the variable. - -@returns ::NC_NOERR No error. -@returns ::NC_EBADID Bad ncid. -@returns ::NC_ENOTVAR Invalid variable ID. -@returns ::NC_EBADNAME Bad name. -@returns ::NC_EMAXNAME Name is too long. -@returns ::NC_ENAMEINUSE Name in use. -@returns ::NC_ENOMEM Out of memory. - -@section nc_rename_var_example Example - -Here is an example using nc_rename_var to rename the variable rh to -rel_hum in an existing netCDF dataset named foo.nc: - -@code - #include - ... - int status; - int ncid; - int rh_id; - ... - 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_rename_var (ncid, rh_id, "rel_hum"); - if (status != NC_NOERR) handle_error(status); - status = nc_enddef(ncid); - if (status != NC_NOERR) handle_error(status); -@endcode -@author Glenn Davis, Ed Hartnett, Dennis Heimbigner + @author Glenn Davis, Ed Hartnett, Dennis Heimbigner */ int -nc_rename_var(int ncid, int varid, const char *name) +nc_def_var(int ncid, const char *name, nc_type xtype, + int ndims, const int *dimidsp, int *varidp) { - NC* ncp; - int stat = NC_check_id(ncid, &ncp); - if(stat != NC_NOERR) return stat; - TRACE(nc_rename_var); - return ncp->dispatch->rename_var(ncid, varid, name); + NC* ncp; + int stat = NC_NOERR; + + if ((stat = NC_check_id(ncid, &ncp))) + return stat; + TRACE(nc_def_var); + return ncp->dispatch->def_var(ncid, name, xtype, ndims, + dimidsp, varidp); } -/*! \} */ /** -@ingroup variables -@internal Does a variable have a record dimension? + Set the fill value for a variable. + + @note For netCDF classic, 64-bit offset, and CDF5 formats, it is + allowed (but not good practice) to set the fill value after data + have been written to the variable. In this case, unless the + variable has been completely specified (without gaps in the data), + any existing filled values will not be recognized as fill values by + applications reading the data. Best practice is to set the fill + value after the variable has been defined, but before any data have + been written to that varibale. In NetCDF-4 files, this is enforced + by the HDF5 library. For netCDF-4 files, an error is returned if + the user attempts to set the fill value after writing data to the + variable. + + @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.) + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ID. + @return ::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_CLASSIC_MODEL flag by + nc_creae(). + @return ::NC_EPERM Attempt to create object in read-only file. + @return ::NC_ELATEDEF (NetCDF-4 only). Returned when user attempts + to set fill value after data are written. + @return ::NC_EGLOBAL Attempt to set fill value on NC_GLOBAL. + + @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; -@param ncid File ID. -@param varid Variable ID. -@param nrecs Pointer that gets number of records. + 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; -@returns 0 if not a record var, 1 if it is. - */ -int -NC_is_recvar(int ncid, int varid, size_t* nrecs) -{ - int status = NC_NOERR; - int unlimid; - int ndims; - int dimset[NC_MAX_VAR_DIMS]; - - status = nc_inq_unlimdim(ncid,&unlimid); - if(status != NC_NOERR) return 0; /* no unlimited defined */ - status = nc_inq_varndims(ncid,varid,&ndims); - if(status != NC_NOERR) return 0; /* no unlimited defined */ - if(ndims == 0) return 0; /* scalar */ - status = nc_inq_vardimid(ncid,varid,dimset); - if(status != NC_NOERR) return 0; /* no unlimited defined */ - status = nc_inq_dim(ncid,dimset[0],NULL,nrecs); - if(status != NC_NOERR) return 0; - return (dimset[0] == unlimid ? 1: 0); -} + if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR; + if (!no_fill) ERR; -/** -@ingroup variables -@internal Get the number of record dimensions for a variable and an -array that identifies which of a variable's dimensions are record -dimensions. Intended to be used instead of NC_is_recvar(), which -doesn't work for netCDF-4 variables which have multiple unlimited -dimensions or an unlimited dimension that is not the first of a -variable's dimensions. - -@param ncid File ID. -@param varid Variable ID. -@param nrecdimsp Pointer that gets number of record dims. -@param is_recdim Pointer that gets 1 if there is one or more record -dimensions, 0 if not. - -@returns 0 if not a record var, 1 if it is. - -Example use: -@code -int nrecdims; -int is_recdim[NC_MAX_VAR_DIMS]; - ... -status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim); -isrecvar = (nrecdims > 0); -@endcode - */ -int -NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim) -{ - int status = NC_NOERR; - int unlimid; - int nvardims; - int dimset[NC_MAX_VAR_DIMS]; - int dim; - int nrecdims = 0; - - status = nc_inq_varndims(ncid,varid,&nvardims); - if(status != NC_NOERR) return status; - if(nvardims == 0) return NC_NOERR; /* scalars have no dims */ - for(dim = 0; dim < nvardims; dim++) - is_recdim[dim] = 0; - status = nc_inq_unlimdim(ncid, &unlimid); - if(status != NC_NOERR) return status; - if(unlimid == -1) return status; /* no unlimited dims for any variables */ -#ifdef USE_NETCDF4 - { - int nunlimdims; - int *unlimids; - int recdim; - status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */ - if(status != NC_NOERR) return status; - if(nunlimdims == 0) return status; - - if (!(unlimids = malloc(nunlimdims * sizeof(int)))) - return NC_ENOMEM; - status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */ - if(status != NC_NOERR) { - free(unlimids); - return status; - } - status = nc_inq_vardimid(ncid, varid, dimset); - if(status != NC_NOERR) { - free(unlimids); - return status; - } - for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */ - for(recdim = 0; recdim < nunlimdims; recdim++) { - if(dimset[dim] == unlimids[recdim]) { - is_recdim[dim] = 1; - nrecdims++; - } - } - } - free(unlimids); - } -#else - status = nc_inq_vardimid(ncid, varid, dimset); - if(status != NC_NOERR) return status; - if(dimset[0] == unlimid) { - is_recdim[0] = 1; - nrecdims++; - } -#endif /* USE_NETCDF4 */ - if(nrecdimsp) *nrecdimsp = nrecdims; - return status; -} + index[0] = 1; + if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR; -/* Ok to use NC pointers because - all IOSP's will use that structure, - but not ok to use e.g. NC_Var pointers - because they may be different structure - entirely. -*/ + index[0] = 0; + if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR; -/** - * @internal - * @ingroup variables - * Find the length of a type. This is how much space is required by - * the in memory to hold one element of this type. - * - * @param type A netCDF atomic type. - * - * @return Length of the type in bytes, or -1 if type not found. - * @author Ed Hartnett - */ + if (nc_close(ncid)) ERR; + @endcode + @author Glenn Davis, Ed Hartnett, Dennis Heimbigner +*/ int -nctypelen(nc_type type) +nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value) { - switch(type){ - case NC_CHAR : - return ((int)sizeof(char)); - case NC_BYTE : - return ((int)sizeof(signed char)); - case NC_SHORT : - return ((int)sizeof(short)); - case NC_INT : - return ((int)sizeof(int)); - case NC_FLOAT : - return ((int)sizeof(float)); - case NC_DOUBLE : - return ((int)sizeof(double)); - - /* These can occur in netcdf-3 code */ - case NC_UBYTE : - return ((int)sizeof(unsigned char)); - case NC_USHORT : - return ((int)(sizeof(unsigned short))); - case NC_UINT : - return ((int)sizeof(unsigned int)); - case NC_INT64 : - return ((int)sizeof(signed long long)); - case NC_UINT64 : - return ((int)sizeof(unsigned long long)); -#ifdef USE_NETCDF4 - case NC_STRING : - return ((int)sizeof(char*)); -#endif /*USE_NETCDF4*/ + NC* ncp; + int stat = NC_check_id(ncid,&ncp); + if(stat != NC_NOERR) return stat; - default: - return -1; - } -} + /* Using NC_GLOBAL is illegal, as this API has no provision for + * specifying the type of the fillvalue, it must of necessity be + * using the type of the variable to interpret the bytes of the + * fill_value argument. */ + if (varid == NC_GLOBAL) return NC_EGLOBAL; -/** \internal -\ingroup variables -Find the length of a type. Redundant over nctypelen() above. */ -size_t -NC_atomictypelen(nc_type xtype) -{ - size_t sz = 0; - switch(xtype) { - case NC_NAT: sz = 0; break; - case NC_BYTE: sz = sizeof(signed char); break; - case NC_CHAR: sz = sizeof(char); break; - case NC_SHORT: sz = sizeof(short); break; - case NC_INT: sz = sizeof(int); break; - case NC_FLOAT: sz = sizeof(float); break; - case NC_DOUBLE: sz = sizeof(double); break; - case NC_INT64: sz = sizeof(signed long long); break; - case NC_UBYTE: sz = sizeof(unsigned char); break; - case NC_USHORT: sz = sizeof(unsigned short); break; - case NC_UINT: sz = sizeof(unsigned int); break; - case NC_UINT64: sz = sizeof(unsigned long long); break; -#ifdef USE_NETCDF4 - case NC_STRING: sz = sizeof(char*); break; -#endif - default: break; - } - return sz; + return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value); } -/** \internal -\ingroup variables - Get the type name. */ -char * -NC_atomictypename(nc_type xtype) -{ - char* nm = NULL; - switch(xtype) { - case NC_NAT: nm = "undefined"; break; - case NC_BYTE: nm = "byte"; break; - case NC_CHAR: nm = "char"; break; - case NC_SHORT: nm = "short"; break; - case NC_INT: nm = "int"; break; - case NC_FLOAT: nm = "float"; break; - case NC_DOUBLE: nm = "double"; break; - case NC_INT64: nm = "int64"; break; - case NC_UBYTE: nm = "ubyte"; break; - case NC_USHORT: nm = "ushort"; break; - case NC_UINT: nm = "uint"; break; - case NC_UINT64: nm = "uint64"; break; #ifdef USE_NETCDF4 - case NC_STRING: nm = "string"; break; -#endif - default: break; - } - return nm; -} +/** + Set the compression settings for a netCDF-4/HDF5 variable. + + This function must be called after nc_def_var and before nc_enddef + or any functions which writes data to the file. + + Deflation and shuffline require chunked data. If this function is + called on a variable with contiguous data, then the data is changed + to chunked data, with default chunksizes. Use nc_def_var_chunking() + to tune performance with user-defined chunksizes. + + If this function is called on a scalar variable, it is ignored. + + @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 + @param shuffle True to turn on the shuffle filter. The shuffle + filter can assist with the compression of integer data by changing + the byte order in the data stream. It makes no sense to use the + shuffle filter without setting a deflate level, or to use shuffle + on non-integer data. + @param deflate True to turn on deflation for this variable. + @param deflate_level A number between 0 (no compression) and 9 + (maximum compression). + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Invalid variable ID. + @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is + not netCDF-4/HDF5. + @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 + netcdf-4 file. + @return ::NC_ELATEDEF Too late to change settings for this variable. + @return ::NC_ENOTINDEFINE Not in define mode. + @return ::NC_EPERM File is read only. + @return ::NC_EMAXDIMS Classic model file exceeds ::NC_MAX_VAR_DIMS. + @return ::NC_ESTRICTNC3 Attempting to create netCDF-4 type var in + classic model file + @return ::NC_EBADTYPE Bad type. + @return ::NC_ENOMEM Out of memory. + @return ::NC_EHDFERR Error returned by HDF5 layer. + @return ::NC_EINVAL Invalid input. Deflate can't be set unless + variable storage is NC_CHUNK. + + @section nc_def_var_deflate_example Example + + Here is an example from /examples/C/simple_xy_nc4_wr.c using + nc_def_var_deflate to create a variable and then turn on the shuffle + filter and compression. + + @code + #include + #define NDIMS 2 + #define NX 6 + #define NY 12 -/** \internal -\ingroup variables -Get the shape of a variable. - */ -int -NC_getshape(int ncid, int varid, int ndims, size_t* shape) -{ - int dimids[NC_MAX_VAR_DIMS]; - int i; - int status = NC_NOERR; + int ncid, x_dimid, y_dimid, varid; + int dimids[NDIMS]; + int shuffle, deflate, deflate_level; + int data_out[NX][NY]; + int x, y, retval; - if ((status = nc_inq_vardimid(ncid, varid, dimids))) - return status; - for(i = 0; i < ndims; i++) - if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i]))) - break; + shuffle = NC_SHUFFLE; + deflate = 1; + deflate_level = 1; + ... + if ((retval = nc_create(FILE_NAME, NC_NETCDF4, &ncid))) + ERR(retval); - return status; -} + if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid))) + ERR(retval); + if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid))) + ERR(retval); -/** - * @ingroup variables - * - * Set the fill value for a variable. - * - * @note For netCDF classic, 64-bit offset, and CDF5 formats, it is - * allowed (but not good practice) to set the fill value after data - * have been written to the variable. In this case, unless the - * variable has been completely specified (without gaps in the data), - * any existing filled values will not be recognized as fill values by - * applications reading the data. Best practice is to set the fill - * value after the variable has been defined, but before any data have - * been written to that varibale. In NetCDF-4 files, this is enforced - * by the HDF5 library. For netCDF-4 files, an error is returned if - * the user attempts to set the fill value after writing data to the - * variable. - - * @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. - * @returns ::NC_ELATEDEF (NetCDF-4 only). Returned when user attempts - * to set fill value after data are written. - * @returns ::NC_EGLOBAL Attempt to set fill value on NC_GLOBAL. - * - * @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 - * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner + dimids[0] = x_dimid; + dimids[1] = y_dimid; + + if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS, + dimids, &varid))) + ERR(retval); + + ... + + if ((retval = nc_def_var_deflate(ncid, varid, shuffle, deflate, + deflate_level))) + ERR(retval); + ... + @endcode + @author Ed Hartnett, Dennis Heimbigner */ int -nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value) +nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level) { NC* ncp; int stat = NC_check_id(ncid,&ncp); if(stat != NC_NOERR) return stat; - - /* Dennis Heimbigner: Using NC_GLOBAL is illegal, as this API has no - * provision for specifying the type of the fillvalue, it must of necessity - * be using the type of the variable to interpret the bytes of the - * fill_value argument. - */ - if (varid == NC_GLOBAL) return NC_EGLOBAL; - - return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value); + return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level); } /** - * @internal Check the start, count, and stride parameters for gets - * and puts, and handle NULLs. - * - * @param ncid The file ID. - * @param varid The variable ID. - * @param start Pointer to start array. If NULL NC_EINVALCOORDS will - * be returned for non-scalar variable. - * @param count Pointer to pointer to count array. If *count is NULL, - * an array of the correct size will be allocated, and filled with - * counts that represent the full extent of the variable. In this - * case, the memory must be freed by the caller. - * @param stride Pointer to pointer to stride array. If NULL, stide is - * ignored. If *stride is NULL an array of the correct size will be - * allocated, and filled with ones. In this case, the memory must be - * freed by the caller. - * - * @return ::NC_NOERR No error. - * @return ::NC_EBADID Bad ncid. - * @return ::NC_ENOTVAR Variable not found. - * @return ::NC_ENOMEM Out of memory. - * @return ::NC_EINVALCOORDS Missing start array. - * @author Ed Hartnett - */ + Set checksum for a var. + + This function must be called after nc_def_var and before nc_enddef + or any functions which writes data to the file. + + Checksums require chunked data. If this function is called on a + variable with contiguous data, then the data is changed to chunked + data, with default chunksizes. Use nc_def_var_chunking() to tune + performance with user-defined chunksizes. + + @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 + @param fletcher32 True to turn on Fletcher32 checksums for this + variable. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Invalid variable ID. + @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is + not netCDF-4/HDF5. + @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 + netcdf-4 file. + @return ::NC_ELATEDEF Too late to change settings for this variable. + @return ::NC_EINVAL Invalid input + @author Ed Hartnett, Dennis Heimbigner +*/ int -NC_check_nulls(int ncid, int varid, const size_t *start, size_t **count, - ptrdiff_t **stride) +nc_def_var_fletcher32(int ncid, int varid, int fletcher32) { - int varndims; - int stat; - - if ((stat = nc_inq_varndims(ncid, varid, &varndims))) - return stat; - - /* For non-scalar vars, start is required. */ - if (!start && varndims) - return NC_EINVALCOORDS; + NC* ncp; + int stat = NC_check_id(ncid,&ncp); + if(stat != NC_NOERR) return stat; + return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32); +} - /* If count is NULL, assume full extent of var. */ - if (!*count) +/** + Define chunking parameters for a variable + + The function nc_def_var_chunking sets the chunking parameters for a + variable in a netCDF-4 file. It can set the chunk sizes to get chunked + storage, or it can set the contiguous flag to get contiguous storage. + + The total size of a chunk must be less than 4 GiB. That is, the + product of all chunksizes and the size of the data (or the size of + nc_vlen_t for VLEN types) must be less than 4 GiB. + + This function may only be called after the variable is defined, but + before nc_enddef is called. Once the chunking parameters are set for a + variable, they cannot be changed. + + Note that this does not work for scalar variables. Only non-scalar + variables can have chunking. + + @param[in] ncid NetCDF ID, from a previous call to nc_open or + nc_create. + + @param[in] varid Variable ID. + + @param[in] storage If ::NC_CONTIGUOUS, then contiguous storage is used + for this variable. Variables with one or more unlimited dimensions + cannot use contiguous storage. If contiguous storage is turned on, the + chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked storage + is used for this variable. Chunk sizes may be specified with the + chunksizes parameter or default sizes will be used if that parameter + is NULL. + + @param[in] chunksizesp A pointer to an array list of chunk sizes. The + array must have one chunksize for each dimension of the variable. If + ::NC_CONTIGUOUS storage is set, then the chunksizes parameter is + ignored. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ID. + @return ::NC_ENOTNC4 Not a netCDF-4 file. + @return ::NC_ELATEDEF This variable has already been the subject of a + nc_enddef call. In netCDF-4 files nc_enddef will be called + automatically for any data read or write. Once nc_enddef has been + called after the nc_def_var call for a variable, it is impossible to + set the chunking for that variable. + @return ::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_CLASSIC_MODEL flag by nc_create(). + @return ::NC_EPERM Attempt to create object in read-only file. + @return ::NC_EBADCHUNK Retunrs if the chunk size specified for a + variable is larger than the length of the dimensions associated with + variable. + + @section nc_def_var_chunking_example Example + + In this example from libsrc4/tst_vars2.c, chunksizes are set with + nc_var_def_chunking, and checked with nc_var_inq_chunking. + + @code + printf("**** testing chunking..."); { - if (!(*count = malloc(varndims * sizeof(size_t)))) - return NC_ENOMEM; - if ((stat = NC_getshape(ncid, varid, varndims, *count))) - { - free(*count); - *count = NULL; - return stat; - } - } + #define NDIMS5 1 + #define DIM5_NAME "D5" + #define VAR_NAME5 "V5" + #define DIM5_LEN 1000 + + int dimids[NDIMS5], dimids_in[NDIMS5]; + int varid; + int ndims, nvars, natts, unlimdimid; + nc_type xtype_in; + char name_in[NC_MAX_NAME + 1]; + int data[DIM5_LEN], data_in[DIM5_LEN]; + size_t chunksize[NDIMS5] = {5}; + size_t chunksize_in[NDIMS5]; + int storage_in; + int i, d; + + for (i = 0; i < DIM5_LEN; i++) + data[i] = i; + + if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; + if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR; + if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR; + if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR; + if (nc_put_var_int(ncid, varid, data)) ERR; + + if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR; + for (d = 0; d < NDIMS5; d++) + if (chunksize[d] != chunksize_in[d]) ERR; + if (storage_in != NC_CHUNKED) ERR; + @endcode +*/ +int +nc_def_var_chunking(int ncid, int varid, int storage, + const size_t *chunksizesp) +{ + NC* ncp; + int stat = NC_check_id(ncid, &ncp); + if(stat != NC_NOERR) return stat; + return ncp->dispatch->def_var_chunking(ncid, varid, storage, + chunksizesp); +} - /* If stride is NULL, do nothing, if *stride is NULL use all 1s. */ - if (stride && !*stride) +/** + Define endianness of a variable. + + With this function the endianness (i.e. order of bits in integers) can + be changed on a per-variable basis. By default, the endianness is the + same as the default endianness of the platform. But with + nc_def_var_endianness the endianness can be explicitly set for a + variable. + + Warning: this function is only defined if the type of the variable + is an atomic integer or float type. + + This function may only be called after the variable is defined, but + before nc_enddef is called. + + @param ncid NetCDF ID, from a previous call to nc_open() or + nc_create(). + + @param varid Variable ID. + + @param endian ::NC_ENDIAN_NATIVE to select the native endianness of + the platform (the default), ::NC_ENDIAN_LITTLE to use + little-endian, ::NC_ENDIAN_BIG to use big-endian. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ID. + @return ::NC_ENOTNC4 Not a netCDF-4 file. + @return ::NC_ELATEDEF This variable has already been the subject of a + nc_enddef call. In netCDF-4 files nc_enddef will be called + automatically for any data read or write. Once nc_enddef has been + called after the nc_def_var call for a variable, it is impossible to + set the chunking for that variable. + @return ::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_CLASSIC_MODEL flag by nc_create(). + @return ::NC_EPERM Attempt to create object in read-only file. + + @section nc_def_var_endian_example Example + + In this example from libsrc4/tst_vars2.c, a variable is created, and + the endianness set to ::NC_ENDIAN_BIG. + + @code + #define NDIMS4 1 + #define DIM4_NAME "Joe" + #define VAR_NAME4 "Ed" + #define DIM4_LEN 10 { - int i; + int dimids[NDIMS4], dimids_in[NDIMS4]; + int varid; + int ndims, nvars, natts, unlimdimid; + nc_type xtype_in; + char name_in[NC_MAX_NAME + 1]; + int data[DIM4_LEN], data_in[DIM4_LEN]; + int endian_in; + int i; - if (!(*stride = malloc(varndims * sizeof(ptrdiff_t)))) - return NC_ENOMEM; - for (i = 0; i < varndims; i++) - (*stride)[i] = 1; - } + for (i = 0; i < DIM4_LEN; i++) + data[i] = i; - return NC_NOERR; + if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; + if (nc_def_dim(ncid, DIM4_NAME, DIM4_LEN, &dimids[0])) ERR; + if (dimids[0] != 0) ERR; + if (nc_def_var(ncid, VAR_NAME4, NC_INT, NDIMS4, dimids, &varid)) ERR; + if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) ERR; + @endcode + @author Ed Hartnett +*/ +int +nc_def_var_endian(int ncid, int varid, int endian) +{ + NC* ncp; + int stat = NC_check_id(ncid,&ncp); + if(stat != NC_NOERR) return stat; + return ncp->dispatch->def_var_endian(ncid,varid,endian); } -/** \ingroup variables -Free string space allocated by the library. - -When you read string type the library will allocate the storage space -for the data. This storage space must be freed, so pass the pointer -back to this function, when you're done with the data, and it will -free the string memory. +/** + Define a new variable filter. -\param len The number of character arrays in the array. -\param data The pointer to the data array. + @param ncid File and group ID. + @param varid Variable ID. + @param id + @param nparams Number of filter parameters. + @param parms Filter parameters. -\returns ::NC_NOERR No error. + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ID. + @author Dennis Heimbigner */ int -nc_free_string(size_t len, char **data) +nc_def_var_filter(int ncid, int varid, unsigned int id, + size_t nparams, const unsigned int* parms) { - int i; - for (i = 0; i < len; i++) - free(data[i]); - return NC_NOERR; + NC* ncp; + int stat = NC_check_id(ncid,&ncp); + if(stat != NC_NOERR) return stat; + return ncp->dispatch->def_var_filter(ncid,varid,id,nparams,parms); } +#endif /* USE_NETCDF4 */ -#ifdef USE_NETCDF4 -/** \ingroup variables +/** @} */ -Change the cache settings for a chunked variable. This function allows -users to control the amount of memory used in the per-variable chunk -cache at the HDF5 level. Changing the chunk cache only has effect -until the file is closed. Once re-opened, the variable chunk cache -returns to its default value. +/** + @name Rename a Variable -\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(). + Rename a variable. +*/ +/** @{ */ -\param varid Variable ID +/** + Rename a variable. -\param size The total size of the raw data chunk cache, in bytes. + This function changes the name of a netCDF variable in an open netCDF + file or group. You cannot rename a variable to have the name of any existing + variable. -\param nelems The number of chunk slots in the raw data chunk cache. + For classic format, 64-bit offset format, and netCDF-4/HDF5 with + classic mode, if the new name is longer than the old name, the netCDF + dataset must be in define mode. -\param preemption The preemption, a value between 0 and 1 inclusive -that indicates how much chunks that have been fully read are favored -for preemption. A value of zero means fully read chunks are treated no -differently than other chunks (the preemption is strictly LRU) while a -value of one means fully read chunks are always preempted before other -chunks. + For netCDF-4/HDF5 files, renaming the variable changes the order of + the variables in the file. The renamed variable becomes the last + variable in the file. -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Bad ncid. -\returns ::NC_ENOTVAR Invalid variable ID. -\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file. -\returns ::NC_EINVAL Invalid input + @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(). -\section nc_def_var_chunk_cache_example Example + @param varid Variable ID -In this example from nc_test4/tst_coords.c, a variable is defined, and -the chunk cache settings are changed for that variable. + @param name New name of the variable. -\code - printf("**** testing setting cache values for coordinate variables..."); - { -#define RANK_1 1 -#define DIM0_NAME "d0" -#define CACHE_SIZE 1000000 -#define CACHE_NELEMS 1009 -#define CACHE_PREEMPTION .90 - - int ncid, dimid, varid; - char name_in[NC_MAX_NAME + 1]; - - if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR; - if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR; - if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR; - if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR; - if (nc_close(ncid)) ERR; - - ... - } - SUMMARIZE_ERR; -\endcode - */ + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Invalid variable ID. + @return ::NC_EBADNAME Bad name. + @return ::NC_EMAXNAME Name is too long. + @return ::NC_ENAMEINUSE Name in use. + @return ::NC_ENOMEM Out of memory. + + @section nc_rename_var_example Example + + Here is an example using nc_rename_var to rename the variable rh to + rel_hum in an existing netCDF dataset named foo.nc: + + @code + #include + ... + int status; + int ncid; + int rh_id; + ... + 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_rename_var (ncid, rh_id, "rel_hum"); + if (status != NC_NOERR) handle_error(status); + status = nc_enddef(ncid); + if (status != NC_NOERR) handle_error(status); + @endcode + @author Glenn Davis, Ed Hartnett, Dennis Heimbigner +*/ int -nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems, - float preemption) +nc_rename_var(int ncid, int varid, const char *name) { NC* ncp; int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; - return ncp->dispatch->set_var_chunk_cache(ncid, varid, size, - nelems, preemption); + TRACE(nc_rename_var); + return ncp->dispatch->rename_var(ncid, varid, name); } +/** @} */ -/** \ingroup variables +/** + @internal Does a variable have a record dimension? -Get the per-variable chunk cache settings from the HDF5 layer. + @param ncid File ID. + @param varid Variable ID. + @param nrecs Pointer that gets number of records. -\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(). + @return 0 if not a record var, 1 if it is. +*/ +int +NC_is_recvar(int ncid, int varid, size_t* nrecs) +{ + int status = NC_NOERR; + int unlimid; + int ndims; + int dimset[NC_MAX_VAR_DIMS]; + + status = nc_inq_unlimdim(ncid,&unlimid); + if(status != NC_NOERR) return 0; /* no unlimited defined */ + status = nc_inq_varndims(ncid,varid,&ndims); + if(status != NC_NOERR) return 0; /* no unlimited defined */ + if(ndims == 0) return 0; /* scalar */ + status = nc_inq_vardimid(ncid,varid,dimset); + if(status != NC_NOERR) return 0; /* no unlimited defined */ + status = nc_inq_dim(ncid,dimset[0],NULL,nrecs); + if(status != NC_NOERR) return 0; + return (dimset[0] == unlimid ? 1: 0); +} -\param varid Variable ID +/** + @internal Get the number of record dimensions for a variable and an + array that identifies which of a variable's dimensions are record + dimensions. Intended to be used instead of NC_is_recvar(), which + doesn't work for netCDF-4 variables which have multiple unlimited + dimensions or an unlimited dimension that is not the first of a + variable's dimensions. + + @param ncid File ID. + @param varid Variable ID. + @param nrecdimsp Pointer that gets number of record dims. + @param is_recdim Pointer that gets 1 if there is one or more record + dimensions, 0 if not. + + @return 0 if not a record var, 1 if it is. + + Example use: + @code + int nrecdims; + int is_recdim[NC_MAX_VAR_DIMS]; + ... + status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim); + isrecvar = (nrecdims > 0); + @endcode +*/ +int +NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim) +{ + int status = NC_NOERR; + int unlimid; + int nvardims; + int dimset[NC_MAX_VAR_DIMS]; + int dim; + int nrecdims = 0; + + status = nc_inq_varndims(ncid,varid,&nvardims); + if(status != NC_NOERR) return status; + if(nvardims == 0) return NC_NOERR; /* scalars have no dims */ + for(dim = 0; dim < nvardims; dim++) + is_recdim[dim] = 0; + status = nc_inq_unlimdim(ncid, &unlimid); + if(status != NC_NOERR) return status; + if(unlimid == -1) return status; /* no unlimited dims for any variables */ +#ifdef USE_NETCDF4 + { + int nunlimdims; + int *unlimids; + int recdim; + status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */ + if(status != NC_NOERR) return status; + if(nunlimdims == 0) return status; + + if (!(unlimids = malloc(nunlimdims * sizeof(int)))) + return NC_ENOMEM; + status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */ + if(status != NC_NOERR) { + free(unlimids); + return status; + } + status = nc_inq_vardimid(ncid, varid, dimset); + if(status != NC_NOERR) { + free(unlimids); + return status; + } + for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */ + for(recdim = 0; recdim < nunlimdims; recdim++) { + if(dimset[dim] == unlimids[recdim]) { + is_recdim[dim] = 1; + nrecdims++; + } + } + } + free(unlimids); + } +#else + status = nc_inq_vardimid(ncid, varid, dimset); + if(status != NC_NOERR) return status; + if(dimset[0] == unlimid) { + is_recdim[0] = 1; + nrecdims++; + } +#endif /* USE_NETCDF4 */ + if(nrecdimsp) *nrecdimsp = nrecdims; + return status; +} -\param sizep The total size of the raw data chunk cache, in bytes, -will be put here. \ref ignored_if_null. +/* Ok to use NC pointers because + all IOSP's will use that structure, + but not ok to use e.g. NC_Var pointers + because they may be different structure + entirely. +*/ -\param nelemsp The number of chunk slots in the raw data chunk cache -hash table will be put here. \ref ignored_if_null. +/** + @internal + Find the length of a type. This is how much space is required by + the in memory to hold one element of this type. -\param preemptionp The preemption will be put here. The preemtion -value is between 0 and 1 inclusive and indicates how much chunks that -have been fully read are favored for preemption. A value of zero means -fully read chunks are treated no differently than other chunks (the -preemption is strictly LRU) while a value of one means fully read -chunks are always preempted before other chunks. \ref ignored_if_null. + @param type A netCDF atomic type. -\returns ::NC_NOERR No error. -\returns ::NC_EBADID Bad ncid. -\returns ::NC_ENOTVAR Invalid variable ID. -\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 -netcdf-4 file. -\returns ::NC_EINVAL Invalid input + @return Length of the type in bytes, or -1 if type not found. + @author Ed Hartnett */ int -nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp, - float *preemptionp) +nctypelen(nc_type type) { - NC* ncp; - int stat = NC_check_id(ncid, &ncp); - if(stat != NC_NOERR) return stat; - return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep, - nelemsp, preemptionp); + switch(type){ + case NC_CHAR : + return ((int)sizeof(char)); + case NC_BYTE : + return ((int)sizeof(signed char)); + case NC_SHORT : + return ((int)sizeof(short)); + case NC_INT : + return ((int)sizeof(int)); + case NC_FLOAT : + return ((int)sizeof(float)); + case NC_DOUBLE : + return ((int)sizeof(double)); + + /* These can occur in netcdf-3 code */ + case NC_UBYTE : + return ((int)sizeof(unsigned char)); + case NC_USHORT : + return ((int)(sizeof(unsigned short))); + case NC_UINT : + return ((int)sizeof(unsigned int)); + case NC_INT64 : + return ((int)sizeof(signed long long)); + case NC_UINT64 : + return ((int)sizeof(unsigned long long)); +#ifdef USE_NETCDF4 + case NC_STRING : + return ((int)sizeof(char*)); +#endif /*USE_NETCDF4*/ + + default: + return -1; + } } /** - * @ingroup variables - * - * Set the compression settings for a netCDF-4/HDF5 variable. - * - * This function must be called after nc_def_var and before nc_enddef - * or any functions which writes data to the file. - * - * Deflation and shuffline require chunked data. If this function is - * called on a variable with contiguous data, then the data is changed - * to chunked data, with default chunksizes. Use nc_def_var_chunking() - * to tune performance with user-defined chunksizes. - * - * If this function is called on a scalar variable, it is ignored. - * - * @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 - * @param shuffle True to turn on the shuffle filter. The shuffle - * filter can assist with the compression of integer data by changing - * the byte order in the data stream. It makes no sense to use the - * shuffle filter without setting a deflate level, or to use shuffle - * on non-integer data. - * @param deflate True to turn on deflation for this variable. - * @param deflate_level A number between 0 (no compression) and 9 - * (maximum compression). - * - * @returns ::NC_NOERR No error. - * @returns ::NC_EBADID Bad ncid. - * @returns ::NC_ENOTVAR Invalid variable ID. - * @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is - * not netCDF-4/HDF5. - * @returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 - * netcdf-4 file. - * @returns ::NC_ELATEDEF Too late to change settings for this variable. - * @returns ::NC_ENOTINDEFINE Not in define mode. - * @returns ::NC_EPERM File is read only. - * @returns ::NC_EMAXDIMS Classic model file exceeds ::NC_MAX_VAR_DIMS. - * @returns ::NC_ESTRICTNC3 Attempting to create netCDF-4 type var in -classic model file - * @returns ::NC_EBADTYPE Bad type. - * @returns ::NC_ENOMEM Out of memory. - * @returns ::NC_EHDFERR Error returned by HDF5 layer. - * @returns ::NC_EINVAL Invalid input. Deflate can't be set unless -variable storage is NC_CHUNK. - -@section nc_def_var_deflate_example Example - -Here is an example from /examples/C/simple_xy_nc4_wr.c using -nc_def_var_deflate to create a variable and then turn on the shuffle -filter and compression. - -@code -#include -#define NDIMS 2 -#define NX 6 -#define NY 12 + @internal + Find the length of a type. Redundant over nctypelen() above. - int ncid, x_dimid, y_dimid, varid; - int dimids[NDIMS]; - int shuffle, deflate, deflate_level; - int data_out[NX][NY]; - int x, y, retval; + @param xtype an nc_type. - shuffle = NC_SHUFFLE; - deflate = 1; - deflate_level = 1; - ... - if ((retval = nc_create(FILE_NAME, NC_NETCDF4, &ncid))) - ERR(retval); + @author Dennis Heimbigner +*/ +size_t +NC_atomictypelen(nc_type xtype) +{ + size_t sz = 0; + switch(xtype) { + case NC_NAT: sz = 0; break; + case NC_BYTE: sz = sizeof(signed char); break; + case NC_CHAR: sz = sizeof(char); break; + case NC_SHORT: sz = sizeof(short); break; + case NC_INT: sz = sizeof(int); break; + case NC_FLOAT: sz = sizeof(float); break; + case NC_DOUBLE: sz = sizeof(double); break; + case NC_INT64: sz = sizeof(signed long long); break; + case NC_UBYTE: sz = sizeof(unsigned char); break; + case NC_USHORT: sz = sizeof(unsigned short); break; + case NC_UINT: sz = sizeof(unsigned int); break; + case NC_UINT64: sz = sizeof(unsigned long long); break; +#ifdef USE_NETCDF4 + case NC_STRING: sz = sizeof(char*); break; +#endif + default: break; + } + return sz; +} - if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid))) - ERR(retval); - if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid))) - ERR(retval); +/** + @internal + Get the type name. - dimids[0] = x_dimid; - dimids[1] = y_dimid; + @param xtype an nc_type. - if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS, - dimids, &varid))) - ERR(retval); + @author Dennis Heimbigner +*/ +char * +NC_atomictypename(nc_type xtype) +{ + char* nm = NULL; + switch(xtype) { + case NC_NAT: nm = "undefined"; break; + case NC_BYTE: nm = "byte"; break; + case NC_CHAR: nm = "char"; break; + case NC_SHORT: nm = "short"; break; + case NC_INT: nm = "int"; break; + case NC_FLOAT: nm = "float"; break; + case NC_DOUBLE: nm = "double"; break; + case NC_INT64: nm = "int64"; break; + case NC_UBYTE: nm = "ubyte"; break; + case NC_USHORT: nm = "ushort"; break; + case NC_UINT: nm = "uint"; break; + case NC_UINT64: nm = "uint64"; break; +#ifdef USE_NETCDF4 + case NC_STRING: nm = "string"; break; +#endif + default: break; + } + return nm; +} - ... +/** + @internal + Get the shape of a variable. - if ((retval = nc_def_var_deflate(ncid, varid, shuffle, deflate, - deflate_level))) - ERR(retval); - ... -@endcode -* @author Ed Hartnett, Dennis Heimbigner + @param ncid NetCDF ID, from a previous call to nc_open() or + nc_create(). + @param varid Variable ID. + @param ndims Number of dimensions for this var. + @param shape Pointer to pre-allocated array that gets the size of + each dimension. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Bad varid. + + @author Dennis Heimbigner */ int -nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level) +NC_getshape(int ncid, int varid, int ndims, size_t* shape) { - NC* ncp; - int stat = NC_check_id(ncid,&ncp); - if(stat != NC_NOERR) return stat; - return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level); + int dimids[NC_MAX_VAR_DIMS]; + int i; + int status = NC_NOERR; + + if ((status = nc_inq_vardimid(ncid, varid, dimids))) + return status; + for(i = 0; i < ndims; i++) + if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i]))) + break; + + return status; } /** - * @ingroup variables - * - * Set checksum for a var. - * - * This function must be called after nc_def_var and before nc_enddef - * or any functions which writes data to the file. - * - * Checksums require chunked data. If this function is called on a - * variable with contiguous data, then the data is changed to chunked - * data, with default chunksizes. Use nc_def_var_chunking() to tune - * performance with user-defined chunksizes. - * - * @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 - * @param fletcher32 True to turn on Fletcher32 checksums for this - * variable. - * - * @returns ::NC_NOERR No error. - * @returns ::NC_EBADID Bad ncid. - * @returns ::NC_ENOTVAR Invalid variable ID. - * @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is -not netCDF-4/HDF5. - * @returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 -netcdf-4 file. - * @returns ::NC_ELATEDEF Too late to change settings for this variable. - * @returns ::NC_EINVAL Invalid input - * @author Ed Hartnett, Dennis Heimbigner + @internal Check the start, count, and stride parameters for gets + and puts, and handle NULLs. + + @param ncid The file ID. + @param varid The variable ID. + @param start Pointer to start array. If NULL ::NC_EINVALCOORDS will + be returned for non-scalar variable. + @param count Pointer to pointer to count array. If *count is NULL, + an array of the correct size will be allocated, and filled with + counts that represent the full extent of the variable. In this + case, the memory must be freed by the caller. + @param stride Pointer to pointer to stride array. If NULL, stide is + ignored. If *stride is NULL an array of the correct size will be + allocated, and filled with ones. In this case, the memory must be + freed by the caller. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Variable not found. + @return ::NC_ENOMEM Out of memory. + @return ::NC_EINVALCOORDS Missing start array. + @author Ed Hartnett */ int -nc_def_var_fletcher32(int ncid, int varid, int fletcher32) +NC_check_nulls(int ncid, int varid, const size_t *start, size_t **count, + ptrdiff_t **stride) { - NC* ncp; - int stat = NC_check_id(ncid,&ncp); - if(stat != NC_NOERR) return stat; - return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32); + int varndims; + int stat; + + if ((stat = nc_inq_varndims(ncid, varid, &varndims))) + return stat; + + /* For non-scalar vars, start is required. */ + if (!start && varndims) + return NC_EINVALCOORDS; + + /* If count is NULL, assume full extent of var. */ + if (!*count) + { + if (!(*count = malloc(varndims * sizeof(size_t)))) + return NC_ENOMEM; + if ((stat = NC_getshape(ncid, varid, varndims, *count))) + { + free(*count); + *count = NULL; + return stat; + } + } + + /* If stride is NULL, do nothing, if *stride is NULL use all + * 1s. */ + if (stride && !*stride) + { + int i; + + if (!(*stride = malloc(varndims * sizeof(ptrdiff_t)))) + return NC_ENOMEM; + for (i = 0; i < varndims; i++) + (*stride)[i] = 1; + } + + return NC_NOERR; } -/*! Define chunking parameters for a variable - -\ingroup variables - -The function nc_def_var_chunking sets the chunking parameters for a -variable in a netCDF-4 file. It can set the chunk sizes to get chunked -storage, or it can set the contiguous flag to get contiguous storage. - -The total size of a chunk must be less than 4 GiB. That is, the -product of all chunksizes and the size of the data (or the size of -nc_vlen_t for VLEN types) must be less than 4 GiB. - -This function may only be called after the variable is defined, but -before nc_enddef is called. Once the chunking parameters are set for a -variable, they cannot be changed. - -Note that this does not work for scalar variables. Only non-scalar -variables can have chunking. - -\param[in] ncid NetCDF ID, from a previous call to nc_open or -nc_create. - -\param[in] varid Variable ID. - -\param[in] storage If ::NC_CONTIGUOUS, then contiguous storage is used -for this variable. Variables with one or more unlimited dimensions -cannot use contiguous storage. If contiguous storage is turned on, the -chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked storage -is used for this variable. Chunk sizes may be specified with the -chunksizes parameter or default sizes will be used if that parameter -is NULL. - -\param[in] chunksizesp A pointer to an array list of chunk sizes. The -array must have one chunksize for each dimension of the variable. If -::NC_CONTIGUOUS storage is set, then the chunksizes parameter is -ignored. - - * @returns ::NC_NOERR No error. - * @returns ::NC_EBADID Bad ID. - * @returns ::NC_ENOTNC4 Not a netCDF-4 file. - * @returns ::NC_ELATEDEF This variable has already been the subject of a -nc_enddef call. In netCDF-4 files nc_enddef will be called -automatically for any data read or write. Once nc_enddef has been -called after the nc_def_var call for a variable, it is impossible to -set the chunking for that variable. - * @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. - * @returns ::NC_EBADCHUNK Retunrs if the chunk size specified for a -variable is larger than the length of the dimensions associated with -variable. - -\section nc_def_var_chunking_example Example - -In this example from libsrc4/tst_vars2.c, chunksizes are set with -nc_var_def_chunking, and checked with nc_var_inq_chunking. - -\code - printf("**** testing chunking..."); - { - #define NDIMS5 1 - #define DIM5_NAME "D5" - #define VAR_NAME5 "V5" - #define DIM5_LEN 1000 - - int dimids[NDIMS5], dimids_in[NDIMS5]; - int varid; - int ndims, nvars, natts, unlimdimid; - nc_type xtype_in; - char name_in[NC_MAX_NAME + 1]; - int data[DIM5_LEN], data_in[DIM5_LEN]; - size_t chunksize[NDIMS5] = {5}; - size_t chunksize_in[NDIMS5]; - int storage_in; - int i, d; - - for (i = 0; i < DIM5_LEN; i++) - data[i] = i; - - if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; - if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR; - if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR; - if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR; - if (nc_put_var_int(ncid, varid, data)) ERR; - - if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR; - for (d = 0; d < NDIMS5; d++) - if (chunksize[d] != chunksize_in[d]) ERR; - if (storage_in != NC_CHUNKED) ERR; -\endcode +/** + @name Free String Resources + + Use this functions to free resources associated with ::NC_STRING + data. +*/ +/*! @{ */ +/** + Free string space allocated by the library. + + When you read string type the library will allocate the storage + space for the data. This storage space must be freed, so pass the + pointer back to this function, when you're done with the data, and + it will free the string memory. + + @param len The number of character arrays in the array. + @param data The pointer to the data array. + + @return ::NC_NOERR No error. + @author Ed Hartnett */ int -nc_def_var_chunking(int ncid, int varid, int storage, - const size_t *chunksizesp) +nc_free_string(size_t len, char **data) { - NC* ncp; - int stat = NC_check_id(ncid, &ncp); - if(stat != NC_NOERR) return stat; - return ncp->dispatch->def_var_chunking(ncid, varid, storage, - chunksizesp); + int i; + for (i = 0; i < len; i++) + free(data[i]); + return NC_NOERR; } +/** @} */ +#ifdef USE_NETCDF4 /** -@ingroup variables - -Define endianness of a variable. - -With this function the endianness (i.e. order of bits in integers) can -be changed on a per-variable basis. By default, the endianness is the -same as the default endianness of the platform. But with -nc_def_var_endianness the endianness can be explicitly set for a -variable. - -Warning: this function is only defined if the type of the variable -is an atomic integer or float type. - -This function may only be called after the variable is defined, but -before nc_enddef is called. - -@param[in] ncid NetCDF ID, from a previous call to nc_open or -nc_create. - -@param[in] varid Variable ID. - -@param[in] endian NC_ENDIAN_NATIVE to select the native endianness of -the platform (the default), NC_ENDIAN_LITTLE to use little-endian, -NC_ENDIAN_BIG to use big-endian. - -@returns ::NC_NOERR No error. -@returns ::NC_EBADID Bad ID. -@returns ::NC_ENOTNC4 Not a netCDF-4 file. -@returns ::NC_ELATEDEF This variable has already been the subject of a -nc_enddef call. In netCDF-4 files nc_enddef will be called -automatically for any data read or write. Once nc_enddef has been -called after the nc_def_var call for a variable, it is impossible to -set the chunking for that variable. -@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_endian_example Example - -In this example from libsrc4/tst_vars2.c, a variable is created, and -the endianness set to NC_ENDIAN_BIG. - -@code -#define NDIMS4 1 -#define DIM4_NAME "Joe" -#define VAR_NAME4 "Ed" -#define DIM4_LEN 10 + @name Variables Chunk Caches + + Use these functions to change the variable chunk cache settings. +*/ +/*! @{ */ +/** + Change the cache settings for a chunked variable. This function allows + users to control the amount of memory used in the per-variable chunk + cache at the HDF5 level. Changing the chunk cache only has effect + until the file is closed. Once re-opened, the variable chunk cache + returns to its default value. + + @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 + @param size The total size of the raw data chunk cache, in bytes. + @param nelems The number of chunk slots in the raw data chunk cache. + @param preemption The preemption, a value between 0 and 1 inclusive + that indicates how much chunks that have been fully read are favored + for preemption. A value of zero means fully read chunks are treated no + differently than other chunks (the preemption is strictly LRU) while a + value of one means fully read chunks are always preempted before other + chunks. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Invalid variable ID. + @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 + netcdf-4 file. + @return ::NC_EINVAL Invalid input + + @section nc_def_var_chunk_cache_example Example + + In this example from nc_test4/tst_coords.c, a variable is defined, and + the chunk cache settings are changed for that variable. + + @code + printf("**** testing setting cache values for coordinate variables..."); { - int dimids[NDIMS4], dimids_in[NDIMS4]; - int varid; - int ndims, nvars, natts, unlimdimid; - nc_type xtype_in; - char name_in[NC_MAX_NAME + 1]; - int data[DIM4_LEN], data_in[DIM4_LEN]; - int endian_in; - int i; - - for (i = 0; i < DIM4_LEN; i++) - data[i] = i; - - if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; - if (nc_def_dim(ncid, DIM4_NAME, DIM4_LEN, &dimids[0])) ERR; - if (dimids[0] != 0) ERR; - if (nc_def_var(ncid, VAR_NAME4, NC_INT, NDIMS4, dimids, &varid)) ERR; - if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) ERR; -@endcode -@author Ed Hartnett + #define RANK_1 1 + #define DIM0_NAME "d0" + #define CACHE_SIZE 1000000 + #define CACHE_NELEMS 1009 + #define CACHE_PREEMPTION .90 + + int ncid, dimid, varid; + char name_in[NC_MAX_NAME + 1]; + + if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR; + if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR; + if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR; + if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR; + if (nc_close(ncid)) ERR; + + ... + } + SUMMARIZE_ERR; + @endcode + @author Ed Hartnett */ int -nc_def_var_endian(int ncid, int varid, int endian) +nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems, + float preemption) { NC* ncp; - int stat = NC_check_id(ncid,&ncp); + int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; - return ncp->dispatch->def_var_endian(ncid,varid,endian); + return ncp->dispatch->set_var_chunk_cache(ncid, varid, size, + nelems, preemption); } /** - * Define a new variable filter. - * - * @param ncid File and group ID. - * @param varid Variable ID. - * @param id - * @param nparams Number of filter parameters. - * @param parms Filter parameters. - * - * @return ::NC_NOERR No error. - * @return ::NC_EBADID Bad ID. - * @author Dennis Heimbigner - */ + Get the per-variable chunk cache settings from the HDF5 layer. + + @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 + @param sizep The total size of the raw data chunk cache, in bytes, + will be put here. @ref ignored_if_null. + @param nelemsp The number of chunk slots in the raw data chunk + cache hash table will be put here. @ref ignored_if_null. + @param preemptionp The preemption will be put here. The preemtion + value is between 0 and 1 inclusive and indicates how much chunks + that have been fully read are favored for preemption. A value of + zero means fully read chunks are treated no differently than other + chunks (the preemption is strictly LRU) while a value of one means + fully read chunks are always preempted before other chunks. @ref + ignored_if_null. + + @return ::NC_NOERR No error. + @return ::NC_EBADID Bad ncid. + @return ::NC_ENOTVAR Invalid variable ID. + @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 + netcdf-4 file. + @return ::NC_EINVAL Invalid input + @author Ed Hartnett +*/ int -nc_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams, const unsigned int* parms) +nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp, + float *preemptionp) { NC* ncp; - int stat = NC_check_id(ncid,&ncp); + int stat = NC_check_id(ncid, &ncp); if(stat != NC_NOERR) return stat; - return ncp->dispatch->def_var_filter(ncid,varid,id,nparams,parms); + return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep, + nelemsp, preemptionp); } - +/** @} */ #endif /* USE_NETCDF4 */ +/** @} */ diff --git a/libdispatch/dvarget.c b/libdispatch/dvarget.c index 0a18108092..9b541800a8 100644 --- a/libdispatch/dvarget.c +++ b/libdispatch/dvarget.c @@ -107,6 +107,7 @@ NC_get_vara(int ncid, int varid, } /** +\internal Get data for a variable. \param ncid NetCDF or group ID. @@ -129,7 +130,6 @@ they are read. \returns ::NC_EBADID Bad ncid. \ingroup variables -\internal \author Dennis Heimbigner */ static int @@ -547,6 +547,7 @@ NCDEFAULT_get_varm(int ncid, int varid, const size_t *start, } /** +\internal Called by externally visible nc_get_vars_xxx routines. \param ncid NetCDF or group ID. @@ -575,7 +576,6 @@ they are read. \returns ::NC_EBADID Bad ncid. \ingroup variables -\internal \author Dennis Heimbigner, Ed Hartnett */ static int @@ -605,6 +605,7 @@ NC_get_vars(int ncid, int varid, const size_t *start, } /** +\internal Called by externally visible nc_get_varm_xxx routines. Note that the varm routines are deprecated. Use the vars routines instead for new code. @@ -637,7 +638,6 @@ they are read. \returns ::NC_EBADID Bad ncid. \ingroup variables -\internal \author Dennis Heimbigner, Ed Hartnett */ static int diff --git a/libhdf5/hdf5dim.c b/libhdf5/hdf5dim.c index 8a146d9014..a184f99251 100644 --- a/libhdf5/hdf5dim.c +++ b/libhdf5/hdf5dim.c @@ -187,6 +187,11 @@ NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp) /** * @internal Rename a dimension, for those who like to prevaricate. * + * @note If we're not in define mode, new name must be of equal or + * less size, if strict nc3 rules are in effect for this file. But we + * don't check this because reproducing the exact classic behavior + * would be too difficult. See github issue #1340. + * * @param ncid File and group ID. * @param dimid Dimension ID. * @param name New dimension name. diff --git a/liblib/Makefile.am b/liblib/Makefile.am index 0a0bab73d7..6c81bec0a3 100644 --- a/liblib/Makefile.am +++ b/liblib/Makefile.am @@ -18,7 +18,7 @@ lib_LTLIBRARIES = libnetcdf.la # for information regarding incrementing `-version-info`. ## -libnetcdf_la_LDFLAGS = -version-info 14:1:1 +libnetcdf_la_LDFLAGS = -version-info 15:0:0 libnetcdf_la_CPPFLAGS = ${AM_CPPFLAGS} libnetcdf_la_LIBADD = diff --git a/nc-config.in b/nc-config.in index 41887de6f2..5138462257 100644 --- a/nc-config.in +++ b/nc-config.in @@ -90,7 +90,7 @@ Available values for OPTION include: --has-parallel4 whether has parallel IO support via HDF5 --has-parallel whether has parallel IO support via HDF5 or PnetCDF --libs library linking information for netcdf - --prefix Install prefixx + --prefix Install prefix --includedir Include directory --libdir Library directory --version Library version diff --git a/nc_test4/tst_filterparser.c b/nc_test4/tst_filterparser.c index 833e981ada..2176c480cf 100644 --- a/nc_test4/tst_filterparser.c +++ b/nc_test4/tst_filterparser.c @@ -172,11 +172,11 @@ buildbaseline(void) insert(7,&val4,sizeof(val4)); /* signed int */ val4 = 4294967295U; /*0xffffffff*/ insert(8,&val4,sizeof(val4)); /* unsigned int */ - float4 = 789.0f; + float4 = (float)FLTVAL; insert(9,&float4,sizeof(float4)); /*float */ - val8 = -9223372036854775807L; + val8 = LONGLONGVAL; insert(10,&val8,sizeof(val8)); /* signed long long */ - val8 = 18446744073709551615UL; + val8 = ULONGLONGVAL; insert(12,&val8,sizeof(val8)); /* unsigned long long */ float8 = DBLVAL; insert(14,&float8,sizeof(float8)); /* double */ @@ -190,6 +190,11 @@ main(int argc, char **argv) unsigned int id = 0; size_t i,nparams = 0; unsigned int* params = NULL; + /* Provide for 8-byte values */ + long long basell; + unsigned long long baseull; + float basef; + double based; printf("\nTesting filter parser.\n"); @@ -211,28 +216,32 @@ main(int argc, char **argv) /* float */ uf.ui = params[9]; - if(uf.f != (float)FLTVAL) + memcpy(&basef,&baseline[9],4); + if(uf.f != basef) mismatch(9,params,"uf.f"); /* signed long long */ ul.ui[0] = params[10]; ul.ui[1] = params[11]; NC_filterfix8((unsigned char*)&ul.ll,1); - if(ul.ll != LONGLONGVAL) + memcpy(&basell,&baseline[10],8); + if(ul.ll != basell) mismatch2(10,params,"ul.ll"); /* unsigned long long */ ul.ui[0] = params[12]; ul.ui[1] = params[13]; NC_filterfix8((unsigned char*)&ul.ull,1); - if(ul.ull != ULONGLONGVAL) + memcpy(&baseull,&baseline[12],8); + if(ul.ull != baseull) mismatch2(12,params,"ul.ull"); /* double */ ud.ui[0] = params[14]; ud.ui[1] = params[15]; NC_filterfix8((unsigned char*)&ud.d,1); - if(ud.d != (double)DBLVAL) + memcpy(&based,&baseline[14],8); + if(ud.d != based) mismatch2(14,params,"ud.d"); if (!nerrs) diff --git a/netcdf.pc.in b/netcdf.pc.in index 089ceec9ed..22b5594b2b 100644 --- a/netcdf.pc.in +++ b/netcdf.pc.in @@ -9,5 +9,5 @@ Description: NetCDF Client Library for C URL: http://www.unidata.ucar.edu/netcdf Version: @PACKAGE_VERSION@ Libs: -L${libdir} @NC_LIBS@ +Libs.private: @LIBS@ Cflags: -I${includedir} - diff --git a/plugins/H5Zbzip2.c b/plugins/H5Zbzip2.c index 993455b438..b840cd5ff7 100644 --- a/plugins/H5Zbzip2.c +++ b/plugins/H5Zbzip2.c @@ -1,3 +1,4 @@ +#include "config.h" #include #include #include @@ -7,6 +8,8 @@ /* Older versions of the hdf library may define H5PL_type_t here */ #include + + #ifndef DLL_EXPORT #define DLL_EXPORT #endif @@ -90,7 +93,11 @@ size_t H5Z_filter_bzip2(unsigned int flags, size_t cd_nelmts, /* Prepare the output buffer. */ outbuflen = nbytes * 3 + 1; /* average bzip2 compression ratio is 3:1 */ +#ifdef HDF5_HAS_ALLOCATE_MEMORY outbuf = H5allocate_memory(outbuflen,0); +#else + outbuf = (char*)malloc(outbuflen * sizeof(char)); +#endif if (outbuf == NULL) { fprintf(stderr, "memory allocation failed for bzip2 decompression\n"); goto cleanupAndFail; @@ -123,7 +130,11 @@ size_t H5Z_filter_bzip2(unsigned int flags, size_t cd_nelmts, if (ret != BZ_STREAM_END && stream.avail_out == 0) { /* Grow the output buffer. */ newbuflen = outbuflen * 2; +#ifdef HDF5_HAS_RESIZE_MEMORY newbuf = H5resize_memory(outbuf, newbuflen); +#else + newbuf = realloc(outbuf,newbuflen); +#endif if (newbuf == NULL) { fprintf(stderr, "memory allocation failed for bzip2 decompression\n"); goto cleanupAndFail; @@ -167,7 +178,12 @@ size_t H5Z_filter_bzip2(unsigned int flags, size_t cd_nelmts, /* Prepare the output buffer. */ outbuflen = nbytes + nbytes / 100 + 600; /* worst case (bzip2 docs) */ +#ifdef HDF5_HAS_ALLOCATE_MEMORY outbuf = H5allocate_memory(outbuflen,0); +#else + outbuf = (char*)malloc(outbuflen * sizeof(char)); +#endif + if (outbuf == NULL) { fprintf(stderr, "memory allocation failed for bzip2 compression\n"); goto cleanupAndFail; @@ -185,13 +201,23 @@ size_t H5Z_filter_bzip2(unsigned int flags, size_t cd_nelmts, } /* Always replace the input buffer with the output buffer. */ +#ifdef HDF5_HAS_H5FREE H5free_memory(*buf); +#else + free(*buf); +#endif + *buf = outbuf; *buf_size = outbuflen; return outdatalen; cleanupAndFail: if (outbuf) +#ifdef HDF5_HAS_H5FREE H5free_memory(outbuf); +#else + free(outbuf); +#endif + return 0; } diff --git a/plugins/H5Zmisc.c b/plugins/H5Zmisc.c index a4b3352622..7a04f1003d 100644 --- a/plugins/H5Zmisc.c +++ b/plugins/H5Zmisc.c @@ -1,3 +1,4 @@ +#include "config.h" #include #include #include @@ -109,21 +110,37 @@ H5Z_filter_test(unsigned int flags, size_t cd_nelmts, if (flags & H5Z_FLAG_REVERSE) { /* Replace buffer */ +#ifdef HDF5_HAS_ALLOCATE_MEMORY newbuf = H5allocate_memory(*buf_size,0); +#else + newbuf = malloc(*buf_size * sizeof(void)); +#endif if(newbuf == NULL) abort(); memcpy(newbuf,*buf,*buf_size); - /* reclaim old buffer */ - H5free_memory(*buf); + /* reclaim old buffer */ +#ifdef HDF5_HAS_H5FREE + H5free_memory(*buf); +#else + free(*buf); +#endif *buf = newbuf; } else { /* Replace buffer */ - newbuf = H5allocate_memory(*buf_size,0); - if(newbuf == NULL) abort(); +#ifdef HDF5_HAS_ALLOCATE_MEMORY + newbuf = H5allocate_memory(*buf_size,0); +#else + newbuf = malloc(*buf_size * sizeof(void)); +#endif + if(newbuf == NULL) abort(); memcpy(newbuf,*buf,*buf_size); /* reclaim old buffer */ - H5free_memory(*buf); +#ifdef HDF5_HAS_H5FREE + H5free_memory(*buf); +#else + free(*buf); +#endif *buf = newbuf; } diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 4c8380eb7e..d439900209 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,6 +1,9 @@ # Copyright 2018, UCAR/Unidata # See netcdf/COPYRIGHT file for copying and redistribution conditions. +# Put Together AM_CPPFLAGS and AM_LDFLAGS +include $(top_srcdir)/lib_flags.am + BZIP2HDRS=bzlib.h bzlib_private.h BZIP2SRC= blocksort.c huffman.c crctable.c randtable.c compress.c decompress.c bzlib.c