Coverage Report

Created: 2026-04-12 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libdispatch/dvar.c
Line
Count
Source
1
/* Copyright 2010-2018 University Corporation for Atmospheric
2
   Research/Unidata. See COPYRIGHT file for more info. */
3
/**
4
 * @file
5
 * Functions for defining and inquiring about variables. @note The
6
 * order of functions in this file affects the doxygen documentation.
7
 *
8
 * @author Dennis Heimbigner, Edward Hartnett
9
 */
10
11
#include "config.h"
12
#include "netcdf.h"
13
#include "netcdf_filter.h"
14
#include "ncdispatch.h"
15
#include "nc4internal.h"
16
#include "netcdf_f.h"
17
#include "nc4internal.h"
18
19
/**
20
   @defgroup variables Variables
21
22
   Variables hold multi-dimensional arrays of data.
23
24
   Variables for a netCDF dataset are defined when the dataset is
25
   created, while the netCDF dataset is in define mode. Other
26
   variables may be added later by reentering define mode. A netCDF
27
   variable has a name, a type, and a shape, which are specified when
28
   it is defined. A variable may also have values, which are
29
   established later in data mode.
30
31
   Ordinarily, the name, type, and shape are fixed when the variable
32
   is first defined. The name may be changed, but the type and shape
33
   of a variable cannot be changed. However, a variable defined in
34
   terms of the unlimited dimension can grow without bound in that
35
   dimension.
36
37
   A netCDF variable in an open netCDF dataset is referred to by a
38
   small integer called a variable ID.
39
40
   Variable IDs reflect the order in which variables were defined
41
   within a netCDF dataset. Variable IDs are 0, 1, 2,..., in the order
42
   in which the variables were defined. A function is available for
43
   getting the variable ID from the variable name and vice-versa.
44
45
   @ref attributes may be associated with a variable to specify such
46
   properties as units.
47
48
   Operations supported on variables are:
49
   - Create a variable, given its name, data type, and shape.
50
   - Get a variable ID from its name.
51
   - Get a variable's name, data type, shape, and number of attributes
52
   from its ID.
53
   - Put a data value into a variable, given variable ID, indices, and value.
54
   - Put an array of values into a variable, given variable ID, corner
55
   indices, edge lengths, and a block of values.
56
   - Put a subsampled or mapped array-section of values into a variable,
57
   given variable ID, corner indices, edge lengths, stride vector,
58
   index mapping vector, and a block of values.
59
   - Get a data value from a variable, given variable ID and indices.
60
   - Get an array of values from a variable, given variable ID, corner
61
   indices, and edge lengths.
62
   - Get a subsampled or mapped array-section of values from a variable,
63
   given variable ID, corner indices, edge lengths, stride vector, and
64
   index mapping vector.
65
   - Rename a variable.
66
67
   @section language_types Data Types
68
69
   NetCDF supported six atomic data types through version 3.6.0 (char,
70
   byte, short, int, float, and double). Starting with version 4.0, many
71
   new atomic and user defined data types are supported (unsigned int
72
   types, strings, compound types, variable length arrays, enums,
73
   opaque).
74
75
   The additional data types are only supported in netCDF-4/HDF5
76
   files. To create netCDF-4/HDF5 files, use the ::NC_NETCDF4 flag in
77
   nc_create().
78
79
   @section classic_types NetCDF-3 Classic and 64-Bit Offset Data Types
80
81
   NetCDF-3 classic and 64-bit offset files support 6 atomic data types,
82
   and none of the user defined datatype introduced in NetCDF-4.
83
84
   The following table gives the netCDF-3 external data types and the
85
   corresponding type constants for defining variables in the C
86
   interface:
87
88
   <table>
89
   <tr><td>Type</td><td>C define</td><td>Bits</td></tr>
90
   <tr><td>byte</td><td>::NC_BYTE</td><td>8</td></tr>
91
   <tr><td>char</td><td>::NC_CHAR</td><td>8</td></tr>
92
   <tr><td>short</td><td>::NC_SHORT</td><td>16</td></tr>
93
   <tr><td>int</td><td>::NC_INT</td><td>32</td></tr>
94
   <tr><td>float</td><td>::NC_FLOAT</td><td>32</td></tr>
95
   <tr><td>double</td><td>::NC_DOUBLE</td><td>64</td></tr>
96
   </table>
97
98
   The first column gives the netCDF external data type, which is the
99
   same as the CDL data type. The next column gives the corresponding C
100
   pre-processor macro for use in netCDF functions (the pre-processor
101
   macros are defined in the netCDF C header-file netcdf.h). The last
102
   column gives the number of bits used in the external representation of
103
   values of the corresponding type.
104
105
   @section netcdf_4_atomic NetCDF-4 Atomic Data Types
106
107
   NetCDF-4 files support all of the atomic data types from netCDF-3,
108
   plus additional unsigned integer types, 64-bit integer types, and a
109
   string type.
110
111
   <table>
112
   <tr><td>Type</td><td>C define</td><td>Bits
113
114
   <tr><td>byte</td><td>::NC_BYTE</td><td>8</td></tr>
115
   <tr><td>unsigned byte </td><td>::NC_UBYTE^</td><td> 8</td></tr>
116
   <tr><td>char </td><td>::NC_CHAR </td><td>8</td></tr>
117
   <tr><td>short </td><td>::NC_SHORT </td><td>16</td></tr>
118
   <tr><td>unsigned short </td><td>::NC_USHORT^ </td><td>16</td></tr>
119
   <tr><td>int </td><td>::NC_INT </td><td>32</td></tr>
120
   <tr><td>unsigned int </td><td>::NC_UINT^ </td><td>32</td></tr>
121
   <tr><td>unsigned long long </td><td>::NC_UINT64^ </td><td>64</td></tr>
122
   <tr><td>long long </td><td>::NC_INT64^ </td><td>64</td></tr>
123
   <tr><td>float </td><td>::NC_FLOAT </td><td>32</td></tr>
124
   <tr><td>double </td><td>::NC_DOUBLE </td><td>64</td></tr>
125
   <tr><td>char ** </td><td>::NC_STRING^ </td><td>string length + 1</td></tr>
126
   </table>
127
128
   ^This type was introduced in netCDF-4, and is not supported in netCDF
129
   classic or 64-bit offset format files, or in netCDF-4 files if they
130
   are created with the ::NC_CLASSIC_MODEL flags.
131
*/
132
133
/** @{ */
134
/**
135
   @name Defining Variables
136
137
   Use these functions to define variables.
138
*/
139
/*! @{ */
140
141
/**
142
   Define a new variable.
143
144
   This function adds a new variable to an open netCDF dataset or group.
145
   It returns (as an argument) a variable ID, given the netCDF ID,
146
   the variable name, the variable type, the number of dimensions, and a
147
   list of the dimension IDs.
148
149
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
150
   nc_create(), nc_def_grp(), or associated inquiry functions such as
151
   nc_inq_ncid().
152
   @param name Variable @ref object_name.
153
   @param xtype (Data
154
   type)[https://docs.unidata.ucar.edu/nug/current/md_types.html#data_type]
155
   of the variable.
156
   @param ndims Number of dimensions for the variable. For example, 2
157
   specifies a matrix, 1 specifies a vector, and 0 means the variable is
158
   a scalar with no dimensions. Must not be negative or greater than the
159
   predefined constant ::NC_MAX_VAR_DIMS. In netCDF-4/HDF5 files, may not
160
   exceed the HDF5 maximum number of dimensions (32).
161
   @param dimidsp Vector of ndims dimension IDs corresponding to the
162
   variable dimensions. For classic model netCDF files, if the ID of the
163
   unlimited dimension is included, it must be first. This argument is
164
   ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there
165
   may be any number of unlimited dimensions, and they may be used in any
166
   element of the dimids array.
167
   @param varidp Pointer to location for the returned variable ID.
168
169
   @return ::NC_NOERR No error.
170
   @return ::NC_EBADID Bad ncid.
171
   @return ::NC_ENOTINDEFINE Not in define mode.
172
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
173
   @return ::NC_EMAXVARS NC_MAX_VARS exceeded [Not enforced after 4.5.0]
174
   @return ::NC_EBADTYPE Bad type.
175
   @return ::NC_EINVAL Invalid input.
176
   @return ::NC_ENAMEINUSE Name already in use.
177
   @return ::NC_EPERM Attempt to create object in read-only file.
178
179
   @section nc_def_var_example Example
180
181
   Here is an example using nc_def_var to create a variable named rh of
182
   type double with three dimensions, time, lat, and lon in a new netCDF
183
   dataset named foo.nc:
184
185
   @code
186
   #include <netcdf.h>
187
   ...
188
   int  status;
189
   int  ncid;
190
   int  lat_dim, lon_dim, time_dim;
191
   int  rh_id;
192
   int  rh_dimids[3];
193
   ...
194
   status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
195
   if (status != NC_NOERR) handle_error(status);
196
   ...
197
198
   status = nc_def_dim(ncid, "lat", 5L, &lat_dim);
199
   if (status != NC_NOERR) handle_error(status);
200
   status = nc_def_dim(ncid, "lon", 10L, &lon_dim);
201
   if (status != NC_NOERR) handle_error(status);
202
   status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
203
   if (status != NC_NOERR) handle_error(status);
204
   ...
205
206
   rh_dimids[0] = time_dim;
207
   rh_dimids[1] = lat_dim;
208
   rh_dimids[2] = lon_dim;
209
   status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id);
210
   if (status != NC_NOERR) handle_error(status);
211
   @endcode
212
213
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
214
*/
215
int
216
nc_def_var(int ncid, const char *name, nc_type xtype,
217
           int ndims,  const int *dimidsp, int *varidp)
218
0
{
219
0
    NC* ncp;
220
0
    int stat = NC_NOERR;
221
222
0
    if ((stat = NC_check_id(ncid, &ncp)))
223
0
        return stat;
224
0
    TRACE(nc_def_var);
225
0
    return ncp->dispatch->def_var(ncid, name, xtype, ndims,
226
0
                                  dimidsp, varidp);
227
0
}
228
229
/**
230
   Set the fill value for a variable.
231
232
   @note For netCDF classic, 64-bit offset, and CDF5 formats, it is
233
   allowed (but not good practice) to set the fill value after data
234
   have been written to the variable. In this case, unless the
235
   variable has been completely specified (without gaps in the data),
236
   any existing filled values will not be recognized as fill values by
237
   applications reading the data. Best practice is to set the fill
238
   value after the variable has been defined, but before any data have
239
   been written to that variable. In NetCDF-4 files, this is enforced
240
   by the HDF5 library. For netCDF-4 files, an error is returned if
241
   the user attempts to set the fill value after writing data to the
242
   variable.
243
244
   @param ncid NetCDF ID, from a previous call to nc_open() or
245
   nc_create().
246
   @param varid Variable ID.
247
   @param no_fill Set to ::NC_NOFILL to turn off fill mode for this
248
   variable. Set to ::NC_FILL (the default) to turn on fill mode for
249
   the variable.
250
   @param fill_value the fill value to be used for this variable. Must
251
   be the same type as the variable. This must point to enough free
252
   memory to hold one element of the data type of the variable. (For
253
   example, an ::NC_INT will require 4 bytes for it's fill value,
254
   which is also an ::NC_INT.)
255
256
   @return ::NC_NOERR No error.
257
   @return ::NC_EBADID Bad ID.
258
   @return ::NC_ENOTINDEFINE Not in define mode.  This is returned for
259
   netCDF classic, 64-bit offset, or 64-bit data files, or for
260
   netCDF-4 files, when they were created with ::NC_CLASSIC_MODEL flag by
261
   nc_create().
262
   @return ::NC_EPERM Attempt to create object in read-only file.
263
   @return ::NC_ELATEDEF (NetCDF-4 only). Returned when user attempts
264
   to set fill value after data are written.
265
   @return ::NC_EGLOBAL Attempt to set fill value on NC_GLOBAL.
266
267
   Warning: Using a vlen type as the fill value may lead to a memory
268
   leak.
269
270
   @section nc_def_var_fill_example Example
271
272
   In this example from libsrc4/tst_vars.c, a variable is defined, and
273
   the fill mode turned off. Then nc_inq_fill() is used to check that
274
   the setting is correct. Then some data are written to the
275
   variable. Since the data that are written do not cover the full
276
   extent of the variable, the missing values will just be random. If
277
   fill value mode was turned on, the missing values would get the
278
   fill value.
279
280
   @code
281
   #define DIM7_LEN 2
282
   #define DIM7_NAME "dim_7_from_Indiana"
283
   #define VAR7_NAME "var_7_from_Idaho"
284
   #define NDIMS 1
285
   int dimids[NDIMS];
286
   size_t index[NDIMS];
287
   int varid;
288
   int no_fill;
289
   unsigned short ushort_data = 42, ushort_data_in, fill_value_in;
290
291
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
292
   if (nc_def_dim(ncid, DIM7_NAME, DIM7_LEN, &dimids[0])) ERR;
293
   if (nc_def_var(ncid, VAR7_NAME, NC_USHORT, NDIMS, dimids,
294
   &varid)) ERR;
295
   if (nc_def_var_fill(ncid, varid, 1, NULL)) ERR;
296
297
   if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR;
298
   if (!no_fill) ERR;
299
300
   index[0] = 1;
301
   if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR;
302
303
   index[0] = 0;
304
   if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR;
305
306
   if (nc_close(ncid)) ERR;
307
   @endcode
308
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
309
*/
310
int
311
nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
312
0
{
313
0
    NC* ncp;
314
0
    int stat = NC_check_id(ncid,&ncp);
315
0
    if(stat != NC_NOERR) return stat;
316
317
    /* Using NC_GLOBAL is illegal, as this API has no provision for
318
     * specifying the type of the fillvalue, it must of necessity be
319
     * using the type of the variable to interpret the bytes of the
320
     * fill_value argument. */
321
0
    if (varid == NC_GLOBAL) return NC_EGLOBAL;
322
323
0
    return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
324
0
}
325
326
/**
327
   Set the zlib compression and shuffle settings for a variable in an
328
   netCDF/HDF5 file.
329
330
   This function must be called after nc_def_var and before nc_enddef
331
   or any functions which writes data to the file.
332
333
   Deflation and shuffle are only available for HDF5 files. Attempting
334
   to set them on non-HDF5 files will return ::NC_ENOTNC4.
335
336
   Deflation and shuffle require chunked data. If this function is
337
   called on a variable with contiguous data, then the data is changed
338
   to chunked data, with default chunksizes. Use nc_def_var_chunking()
339
   to tune performance with user-defined chunksizes.
340
341
   If this function is called on a scalar variable, ::NC_EINVAL is
342
   returned. Only chunked variables may use filters.
343
344
   Zlib compression cannot be used with szip compression. If this
345
   function is called on a variable which already has szip compression
346
   turned on, ::NC_EINVAL is returned.
347
348
   @note Parallel I/O reads work with compressed data. Parallel I/O
349
   writes work with compressed data in netcdf-c-4.7.4 and later
350
   releases, using hdf5-1.10.3 and later releases. Using the zlib,
351
   shuffle (or any other) filter requires that collective access be
352
   used with the variable. Turning on deflate and/or shuffle for a
353
   variable in a file opened for parallel I/O will automatically
354
   switch the access for that variable to collective access.
355
356
   @note The HDF5 manual has this to say about shuffle:
357
   
358
      The shuffle filter de-interlaces a block of data by reordering
359
      the bytes. All the bytes from one consistent byte position of
360
      each data element are placed together in one block; all bytes
361
      from a second consistent byte position of each data element are
362
      placed together a second block; etc. For example, given three
363
      data elements of a 4-byte datatype stored as 012301230123,
364
      shuffling will re-order data as 000111222333. This can be a
365
      valuable step in an effective compression algorithm because the
366
      bytes in each byte position are often closely related to each
367
      other and putting them together can increase the compression
368
      ratio.
369
370
      As implied above, the primary value of the shuffle filter lies
371
      in its coordinated use with a compression filter; it does not
372
      provide data compression when used alone. When the shuffle
373
      filter is applied to a dataset immediately prior to the use of a
374
      compression filter, the compression ratio achieved is often
375
      superior to that achieved by the use of a compression filter
376
      without the shuffle filter.
377
378
  @note The shuffle and deflate flags are ambiguous.
379
380
  In most cases, if the shuffle or deflate flag is zero, then it is interpreted
381
  to mean that shuffle or deflate should not be set. However, if the variable
382
  already has shuffle or deflate turned on, then it is unclear if a flag
383
  value of zero means leave the state as it is, or if it means
384
  that it should be turned off. Since currently no other filters can be
385
  disabled, it is assumed here that a zero value means to leave the
386
  state as it is.
387
388
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
389
   nc_create(), nc_def_grp(), or associated inquiry functions such as
390
   nc_inq_ncid().
391
   @param varid Variable ID
392
   @param shuffle True to turn on the shuffle filter. The shuffle
393
   filter can assist with the compression of data by changing the byte
394
   order in the data stream. It makes no sense to use the shuffle
395
   filter without setting a deflate level.
396
   @param deflate True to turn on deflation for this variable.
397
   @param deflate_level A number between 0 (no compression) and 9
398
   (maximum compression).
399
400
   @return ::NC_NOERR No error.
401
   @return ::NC_EBADID Bad ncid.
402
   @return ::NC_ENOTVAR Invalid variable ID.
403
   @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
404
   not netCDF-4/HDF5.
405
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
406
   netcdf-4 file.
407
   @return ::NC_ELATEDEF Too late to change settings for this variable.
408
   @return ::NC_ENOTINDEFINE Not in define mode.
409
   @return ::NC_EPERM File is read only.
410
   @return ::NC_ESTRICTNC3 Attempting to create netCDF-4 type var in
411
   classic model file
412
   @return ::NC_EHDFERR Error returned by HDF5 layer.
413
   @return ::NC_EINVAL Invalid input. Deflate can't be set unless
414
   variable storage is NC_CHUNK.
415
416
   @section nc_def_var_deflate_example Example
417
418
   Here is an example from /examples/C/simple_xy_nc4_wr.c using
419
   nc_def_var_deflate to create a variable and then turn on the shuffle
420
   filter and compression.
421
422
   @code
423
   #include <netcdf.h>
424
   #define NDIMS 2
425
   #define NX 6
426
   #define NY 12
427
428
   int ncid, x_dimid, y_dimid, varid;
429
   int dimids[NDIMS];
430
   int shuffle, deflate, deflate_level;
431
   int data_out[NX][NY];
432
   int x, y, retval;
433
434
   shuffle = NC_SHUFFLE;
435
   deflate = 1;
436
   deflate_level = 1;
437
   ...
438
   if ((retval = nc_create(FILE_NAME, NC_NETCDF4, &ncid)))
439
   ERR(retval);
440
441
   if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid)))
442
   ERR(retval);
443
   if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid)))
444
   ERR(retval);
445
446
   dimids[0] = x_dimid;
447
   dimids[1] = y_dimid;
448
449
   if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS,
450
   dimids, &varid)))
451
   ERR(retval);
452
453
   ...
454
455
   if ((retval = nc_def_var_deflate(ncid, varid, shuffle, deflate,
456
   deflate_level)))
457
   ERR(retval);
458
   ...
459
   @endcode
460
   @author Ed Hartnett, Dennis Heimbigner
461
*/
462
int
463
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level)
464
0
{
465
0
    NC* ncp;
466
0
    int stat = NC_check_id(ncid,&ncp);
467
0
    if(stat != NC_NOERR) return stat;
468
0
    return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level);
469
0
}
470
471
/**
472
   Turn on quantization for a variable.
473
  
474
   The data are quantized by setting unneeded bits to zeros or ones
475
   so that they may compress well. BitGroom sets bits alternately to 1/0, 
476
   while BitRound and Granular BitRound (GBR) round (more) bits to zeros
477
   Quantization is lossy (data are irretrievably altered), and it 
478
   improves the compression ratio provided by a subsequent lossless 
479
   compression filter. Quantization alone will not reduce the data size.
480
   Lossless compression like zlib must also be used (see nc_def_var_deflate()).
481
482
   Producers of large datasets may find that using quantize with
483
   compression will result in significant improvement in the final data
484
   size.
485
486
   A notable feature of all the quantization algorithms is data remain 
487
   in IEEE754 format afterwards. Therefore quantization algorithms do
488
   nothing when data are read.
489
  
490
   Quantization is only available for variables of type NC_FLOAT or
491
   NC_DOUBLE. Attempts to set quantization for other variable
492
   types return an error (NC_EINVAL). 
493
494
   Variables that use quantize will have added an attribute with name
495
   NC_QUANTIZE_[ALGORITHM_NAME]_ATT_NAME, which will contain the 
496
   number of significant digits. Users should not delete or change this
497
   attribute. This is the only record that quantize has been applied
498
   to the data.
499
500
   Quantization is not applied to values equal to the value of the
501
   _FillValue attribute, if any. If the _FillValue attribute is not
502
   set, then quantization is not applied to values matching the
503
   default fill value.
504
505
   Quantization may be applied to scalar variables.
506
507
   When type conversion takes place during a write, then it occurs
508
   before quantization is applied. For example, if nc_put_var_double()
509
   is called on a variable of type NC_FLOAT, which has quantize
510
   turned on, then the data are first converted from double to float,
511
   then quantization is applied to the float values.
512
513
   As with the deflate settings, quantize settings may only be
514
   modified before the first call to nc_enddef(). Once nc_enddef() is
515
   called for the file, quantize settings for any variable in the file
516
   may not be changed.
517
 
518
   Use of quantization is fully backwards compatible with existing
519
   versions and packages that can read compressed netCDF data. A
520
   variable which has been quantized is readable to older versions of
521
   the netCDF libraries, and to netCDF-Java.
522
 
523
   For more information about quantization and the BitGroom filter,
524
   see @ref quantize.
525
526
   @note Users new to quantization should start with Granular Bit
527
   Round, which results in the best compression. The Bit Groom
528
   algorithm is not as effective when compressing, but is faster than
529
   Granular Bit Round. The Bit Round algorithm accepts a number of
530
   bits to maintain, rather than a number of decimal digits, and is
531
   provided for users who are already performing some bit-based
532
   quantization, and wish to turn this task over to the netCDF
533
   library.
534
535
   @param ncid File ID.
536
   @param varid Variable ID. ::NC_GLOBAL may not be used.
537
   @param quantize_mode Quantization mode. May be ::NC_NOQUANTIZE or
538
   ::NC_QUANTIZE_BITGROOM or ::NC_QUANTIZE_GRANULARBR or
539
   ::NC_QUANTIZE_BITROUND.
540
   @param nsd Number of significant digits (either decimal or binary). 
541
   May be any integer from 1 to ::NC_QUANTIZE_MAX_FLOAT_NSD (for variables 
542
   of type ::NC_FLOAT) or ::NC_QUANTIZE_MAX_DOUBLE_NSD (for variables 
543
   of type ::NC_DOUBLE) for mode ::NC_QUANTIZE_BITGROOM and mode
544
   ::NC_QUANTIZE_GRANULARBR. May be any integer from 1 to 
545
   ::NC_QUANTIZE_MAX_FLOAT_NSB (for variables of type ::NC_FLOAT) or 
546
   ::NC_QUANTIZE_MAX_DOUBLE_NSB (for variables of type ::NC_DOUBLE) 
547
   for mode ::NC_QUANTIZE_BITROUND. Ignored if quantize_mode = NC_NOQUANTIZE.
548
   
549
   @return ::NC_NOERR No error.
550
   @return ::NC_EGLOBAL Can't use ::NC_GLOBAL with this function.
551
   @return ::NC_EBADID Bad ncid.
552
   @return ::NC_ENOTVAR Invalid variable ID.
553
   @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
554
   not netCDF-4/HDF5.
555
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
556
   netcdf-4 file.
557
   @return ::NC_ELATEDEF Too late to change settings for this variable.
558
   @return ::NC_EINVAL Invalid input.
559
   @since 4.9.0
560
   @author Charlie Zender, Ed Hartnett
561
 */
562
int
563
nc_def_var_quantize(int ncid, int varid, int quantize_mode, int nsd)
564
0
{
565
0
    NC* ncp;
566
0
    int stat = NC_check_id(ncid,&ncp);
567
0
    if(stat != NC_NOERR) return stat;
568
569
    /* Using NC_GLOBAL is illegal. */
570
0
    if (varid == NC_GLOBAL) return NC_EGLOBAL;
571
0
    return ncp->dispatch->def_var_quantize(ncid,varid,quantize_mode,nsd);
572
0
}
573
574
/**
575
   Set checksum for a var.
576
577
   This function must be called after nc_def_var and before nc_enddef
578
   or any functions which writes data to the file.
579
580
   Checksums require chunked data. If this function is called on a
581
   variable with contiguous data, then the data is changed to chunked
582
   data, with default chunksizes. Use nc_def_var_chunking() to tune
583
   performance with user-defined chunksizes.
584
585
   @note Parallel I/O reads work with fletcher32 encoded
586
   data. Parallel I/O writes work with fletcher32 in netcdf-c-4.7.4
587
   and later releases, using hdf5-1.10.2 and later releases. Using the
588
   fletcher32 (or any) filter requires that collective access be used
589
   with the variable. Turning on fletcher32 for a variable in a file
590
   opened for parallel I/O will automatically switch the access for
591
   that variable to collective access.
592
593
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
594
   nc_create(), nc_def_grp(), or associated inquiry functions such as
595
   nc_inq_ncid().
596
   @param varid Variable ID
597
   @param fletcher32 True to turn on Fletcher32 checksums for this
598
   variable.
599
600
   @return ::NC_NOERR No error.
601
   @return ::NC_EBADID Bad ncid.
602
   @return ::NC_ENOTVAR Invalid variable ID.
603
   @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
604
   not netCDF-4/HDF5.
605
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
606
   netcdf-4 file.
607
   @return ::NC_ELATEDEF Too late to change settings for this variable.
608
   @return ::NC_EINVAL Invalid input
609
   @author Ed Hartnett, Dennis Heimbigner
610
*/
611
int
612
nc_def_var_fletcher32(int ncid, int varid, int fletcher32)
613
0
{
614
0
    NC* ncp;
615
0
    int stat = NC_check_id(ncid,&ncp);
616
0
    if(stat != NC_NOERR) return stat;
617
0
    return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32);
618
0
}
619
620
/**
621
   Define storage and, if chunked storage is used, chunking parameters
622
   for a variable
623
624
   The storage may be set to NC_CONTIGUOUS, NC_COMPACT, or NC_CHUNKED.
625
626
   Contiguous storage means the variable is stored as one block of
627
   data in the file. This is the default storage.
628
629
   Compact storage means the variable is stored in the header record
630
   of the file. This can have large performance benefits on HPC system
631
   running many processors. Compact storage is only available for
632
   variables whose data are 64 KB or less. Attempting to turn on
633
   compact storage for a variable that is too large will result in the
634
   ::NC_EVARSIZE error.
635
636
   Chunked storage means the data are stored as chunks, of
637
   user-configurable size. Chunked storage is required for variable
638
   with one or more unlimited dimensions, or variable which use
639
   compression, or any other filter.
640
641
   The total size of a chunk must be less than 4 GiB. That is, the
642
   product of all chunksizes and the size of the data (or the size of
643
   nc_vlen_t for VLEN types) must be less than 4 GiB.
644
645
   This function may only be called after the variable is defined, but
646
   before nc_enddef is called. Once the chunking parameters are set for a
647
   variable, they cannot be changed.
648
649
   @note Scalar variables may have a storage of NC_CONTIGUOUS or
650
   NC_COMPACT. Attempts to set chunking on a scalar variable will
651
   cause ::NC_EINVAL to be returned. Only non-scalar variables can
652
   have chunking.
653
654
   @param ncid NetCDF ID, from a previous call to nc_open() or
655
   nc_create().
656
   @param varid Variable ID.
657
   @param storage If ::NC_CONTIGUOUS or ::NC_COMPACT, then contiguous
658
   or compact storage is used for this variable. Variables with one or
659
   more unlimited dimensions cannot use contiguous or compact
660
   storage. If contiguous or compact storage is turned on, the
661
   chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked
662
   storage is used for this variable. Chunk sizes may be specified
663
   with the chunksizes parameter or default sizes will be used if that
664
   parameter is NULL.
665
   @param chunksizesp A pointer to an array list of chunk sizes. The
666
   array must have one chunksize for each dimension of the variable. If
667
   ::NC_CONTIGUOUS storage is set, then the chunksizes parameter is
668
   ignored. Ignored if NULL.
669
670
   @return ::NC_NOERR No error.
671
   @return ::NC_EBADID Bad ID.
672
   @return ::NC_ENOTNC4 Not a netCDF-4 file.
673
   @return ::NC_ELATEDEF This variable has already been the subject of
674
   a nc_enddef call.  In netCDF-4 files nc_enddef will be called
675
   automatically for any data read or write. Once nc_enddef has been
676
   called after the nc_def_var call for a variable, it is impossible
677
   to set the chunking for that variable.
678
   @return ::NC_ENOTINDEFINE Not in define mode.  This is returned for
679
   netCDF classic or 64-bit offset files, or for netCDF-4 files, when
680
   they were created with ::NC_CLASSIC_MODEL flag by nc_create().
681
   @return ::NC_EPERM Attempt to create object in read-only file.
682
   @return ::NC_EBADCHUNK Returns if the chunk size specified for a
683
   variable is larger than the length of the dimensions associated with
684
   variable.
685
   @return ::NC_EVARSIZE Compact storage attempted for variable bigger
686
   than 64 KB.
687
   @return ::NC_EINVAL Attempt to set contiguous or compact storage
688
   for var with one or more unlimited dimensions, or chunking for a
689
   scalar var.
690
691
   @section nc_def_var_chunking_example Example
692
693
   In this example from libsrc4/tst_vars2.c, chunksizes are set with
694
   nc_var_def_chunking, and checked with nc_var_inq_chunking.
695
696
   @code
697
   printf("**** testing chunking...");
698
   {
699
   #define NDIMS5 1
700
   #define DIM5_NAME "D5"
701
   #define VAR_NAME5 "V5"
702
   #define DIM5_LEN 1000
703
704
   int dimids[NDIMS5], dimids_in[NDIMS5];
705
   int varid;
706
   int ndims, nvars, natts, unlimdimid;
707
   nc_type xtype_in;
708
   char name_in[NC_MAX_NAME + 1];
709
   int data[DIM5_LEN], data_in[DIM5_LEN];
710
   size_t chunksize[NDIMS5] = {5};
711
   size_t chunksize_in[NDIMS5];
712
   int storage_in;
713
   int i, d;
714
715
   for (i = 0; i < DIM5_LEN; i++)
716
   data[i] = i;
717
718
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
719
   if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR;
720
   if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR;
721
   if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR;
722
   if (nc_put_var_int(ncid, varid, data)) ERR;
723
724
   if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR;
725
   for (d = 0; d < NDIMS5; d++)
726
   if (chunksize[d] != chunksize_in[d]) ERR;
727
   if (storage_in != NC_CHUNKED) ERR;
728
   @endcode
729
   @author Ed Hartnett, Dennis Heimbigner
730
*/
731
int
732
nc_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp)
733
0
{
734
0
    NC* ncp;
735
0
    int stat = NC_check_id(ncid, &ncp);
736
0
    if(stat != NC_NOERR) return stat;
737
0
    return ncp->dispatch->def_var_chunking(ncid, varid, storage,
738
0
                                           chunksizesp);
739
0
}
740
741
/**
742
   Define endianness of a variable.
743
744
   With this function the endianness (i.e. order of bytes in integers) can
745
   be changed on a per-variable basis. By default, the endianness is the
746
   same as the default endianness of the platform. But with
747
   nc_def_var_endianness the endianness can be explicitly set for a
748
   variable.
749
750
   Warning: this function is only defined if the type of the variable
751
   is an atomic integer or float type.
752
753
   This function may only be called after the variable is defined, but
754
   before nc_enddef is called.
755
756
   @param ncid NetCDF ID, from a previous call to nc_open() or
757
   nc_create().
758
759
   @param varid Variable ID.
760
761
   @param endian ::NC_ENDIAN_NATIVE to select the native endianness of
762
   the platform (the default), ::NC_ENDIAN_LITTLE to use
763
   little-endian, ::NC_ENDIAN_BIG to use big-endian.
764
765
   @return ::NC_NOERR No error.
766
   @return ::NC_EBADID Bad ID.
767
   @return ::NC_ENOTNC4 Not a netCDF-4 file.
768
   @return ::NC_ELATEDEF This variable has already been the subject of a
769
   nc_enddef call. In netCDF-4 files nc_enddef will be called
770
   automatically for any data read or write. Once nc_enddef has been
771
   called after the nc_def_var call for a variable, it is impossible to
772
   set the chunking for that variable.
773
   @return ::NC_ENOTINDEFINE Not in define mode. This is returned for
774
   netCDF classic or 64-bit offset files, or for netCDF-4 files, when
775
   they were created with ::NC_CLASSIC_MODEL flag by nc_create().
776
   @return ::NC_EPERM Attempt to create object in read-only file.
777
778
   @section nc_def_var_endian_example Example
779
780
   In this example from libsrc4/tst_vars2.c, a variable is created, and
781
   the endianness set to ::NC_ENDIAN_BIG.
782
783
   @code
784
   #define NDIMS4 1
785
   #define DIM4_NAME "Joe"
786
   #define VAR_NAME4 "Ed"
787
   #define DIM4_LEN 10
788
   {
789
   int dimids[NDIMS4], dimids_in[NDIMS4];
790
   int varid;
791
   int ndims, nvars, natts, unlimdimid;
792
   nc_type xtype_in;
793
   char name_in[NC_MAX_NAME + 1];
794
   int data[DIM4_LEN], data_in[DIM4_LEN];
795
   int endian_in;
796
   int i;
797
798
   for (i = 0; i < DIM4_LEN; i++)
799
   data[i] = i;
800
801
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
802
   if (nc_def_dim(ncid, DIM4_NAME, DIM4_LEN, &dimids[0])) ERR;
803
   if (dimids[0] != 0) ERR;
804
   if (nc_def_var(ncid, VAR_NAME4, NC_INT, NDIMS4, dimids, &varid)) ERR;
805
   if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) ERR;
806
   @endcode
807
   @author Ed Hartnett
808
*/
809
int
810
nc_def_var_endian(int ncid, int varid, int endian)
811
0
{
812
0
    NC* ncp;
813
0
    int stat = NC_check_id(ncid,&ncp);
814
0
    if(stat != NC_NOERR) return stat;
815
0
    return ncp->dispatch->def_var_endian(ncid,varid,endian);
816
0
}
817
818
/**
819
 * Set szip compression settings on a variable. Szip is an
820
 * implementation of the extended-Rice lossless compression algorithm;
821
 * it is reported to provide fast and effective compression. Szip is
822
 * only available to netCDF if HDF5 was built with szip support.
823
 *
824
 * SZIP compression cannot be applied to variables with any
825
 * user-defined type.
826
 *
827
 * If zlib compression has already be turned on for a variable, then
828
 * this function will return ::NC_EINVAL.
829
 *
830
 * To learn the szip settings for a variable, use nc_inq_var_szip().
831
 *
832
 * @note The options_mask parameter may be either ::NC_SZIP_EC (entropy
833
 * coding) or ::NC_SZIP_NN (nearest neighbor):
834
 * * The entropy coding method is best suited for data that has been
835
 * processed. The EC method works best for small numbers.
836
 * * The nearest neighbor coding method preprocesses the data then the
837
 * applies EC method as above.
838
 *
839
 * For more information about HDF5 and szip, see
840
 * https://support.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSzip
841
 * and
842
 * https://support.hdfgroup.org/doc_resource/SZIP/index.html.
843
 *
844
 * @param ncid File ID.
845
 * @param varid Variable ID.
846
 * @param options_mask The options mask. Can be ::NC_SZIP_EC or
847
 * ::NC_SZIP_NN.
848
 * @param pixels_per_block Pixels per block. Must be even and not
849
 * greater than 32, with typical values being 8, 10, 16, or 32. This
850
 * parameter affects compression ratio; the more pixel values vary,
851
 * the smaller this number should be to achieve better performance. If
852
 * pixels_per_block is bigger than the total number of elements in a
853
 * dataset chunk, ::NC_EINVAL will be returned.
854
 *
855
 * @returns ::NC_NOERR No error.
856
 * @returns ::NC_EBADID Bad ncid.
857
 * @returns ::NC_ENOTVAR Invalid variable ID.
858
 * @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
859
 * not netCDF-4/HDF5.
860
 * @returns ::NC_ELATEDEF Too late to change settings for this variable.
861
 * @returns ::NC_ENOTINDEFINE Not in define mode.
862
 * @returns ::NC_EINVAL Invalid input, or zlib filter already applied
863
 * to this var.
864
 * @since 4.0.0
865
 * @author Ed Hartnett
866
 */
867
int
868
nc_def_var_szip(int ncid, int varid, int options_mask, int pixels_per_block)
869
0
{
870
0
    int ret;
871
872
    /* This will cause H5Pset_szip to be called when the var is
873
     * created. */
874
0
    unsigned int params[2] = {(unsigned int)options_mask, (unsigned int)pixels_per_block};
875
0
    if ((ret = nc_def_var_filter(ncid, varid, H5Z_FILTER_SZIP, 2, params)))
876
0
        return ret;
877
878
0
    return NC_NOERR;
879
0
}
880
881
/** @} */
882
883
/**
884
   @name Rename a Variable
885
886
   Rename a variable.
887
*/
888
/** @{ */
889
890
/**
891
   Rename a variable.
892
893
   This function changes the name of a netCDF variable in an open netCDF
894
   file or group. You cannot rename a variable to have the name of any existing
895
   variable.
896
897
   For classic format, 64-bit offset format, and netCDF-4/HDF5 with
898
   classic mode, if the new name is longer than the old name, the netCDF
899
   dataset must be in define mode.
900
901
   For netCDF-4/HDF5 files, renaming the variable changes the order of
902
   the variables in the file. The renamed variable becomes the last
903
   variable in the file.
904
905
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
906
   nc_create(), nc_def_grp(), or associated inquiry functions such as
907
   nc_inq_ncid().
908
909
   @param varid Variable ID
910
911
   @param name New name of the variable.
912
913
   @return ::NC_NOERR No error.
914
   @return ::NC_EBADID Bad ncid.
915
   @return ::NC_ENOTVAR Invalid variable ID.
916
   @return ::NC_EBADNAME Bad name.
917
   @return ::NC_EMAXNAME Name is too long.
918
   @return ::NC_ENAMEINUSE Name in use.
919
   @return ::NC_ENOMEM Out of memory.
920
921
   @section nc_rename_var_example Example
922
923
   Here is an example using nc_rename_var to rename the variable rh to
924
   rel_hum in an existing netCDF dataset named foo.nc:
925
926
   @code
927
   #include <netcdf.h>
928
   ...
929
   int  status;
930
   int  ncid;
931
   int  rh_id;
932
   ...
933
   status = nc_open("foo.nc", NC_WRITE, &ncid);
934
   if (status != NC_NOERR) handle_error(status);
935
   ...
936
   status = nc_redef(ncid);
937
   if (status != NC_NOERR) handle_error(status);
938
   status = nc_inq_varid (ncid, "rh", &rh_id);
939
   if (status != NC_NOERR) handle_error(status);
940
   status = nc_rename_var (ncid, rh_id, "rel_hum");
941
   if (status != NC_NOERR) handle_error(status);
942
   status = nc_enddef(ncid);
943
   if (status != NC_NOERR) handle_error(status);
944
   @endcode
945
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
946
*/
947
int
948
nc_rename_var(int ncid, int varid, const char *name)
949
0
{
950
0
    NC* ncp;
951
0
    int stat = NC_check_id(ncid, &ncp);
952
0
    if(stat != NC_NOERR) return stat;
953
0
    TRACE(nc_rename_var);
954
0
    return ncp->dispatch->rename_var(ncid, varid, name);
955
0
}
956
/** @} */
957
958
/**
959
   @internal Does a variable have a record dimension?
960
961
   @param ncid File ID.
962
   @param varid Variable ID.
963
   @param nrecs Pointer that gets number of records.
964
965
   @return 0 if not a record var, 1 if it is.
966
*/
967
int
968
NC_is_recvar(int ncid, int varid, size_t* nrecs)
969
0
{
970
0
    int status = NC_NOERR;
971
0
    int unlimid;
972
0
    int ndims;
973
0
    int dimset[NC_MAX_VAR_DIMS];
974
975
0
    status = nc_inq_unlimdim(ncid,&unlimid);
976
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
977
0
    status = nc_inq_varndims(ncid,varid,&ndims);
978
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
979
0
    if(ndims == 0) return 0; /* scalar */
980
0
    status = nc_inq_vardimid(ncid,varid,dimset);
981
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
982
0
    status = nc_inq_dim(ncid,dimset[0],NULL,nrecs);
983
0
    if(status != NC_NOERR) return 0;
984
0
    return (dimset[0] == unlimid ? 1: 0);
985
0
}
986
987
/**
988
   @internal Get the number of record dimensions for a variable and an
989
   array that identifies which of a variable's dimensions are record
990
   dimensions. Intended to be used instead of NC_is_recvar(), which
991
   doesn't work for netCDF-4 variables which have multiple unlimited
992
   dimensions or an unlimited dimension that is not the first of a
993
   variable's dimensions.
994
995
   @param ncid File ID.
996
   @param varid Variable ID.
997
   @param nrecdimsp Pointer that gets number of record dims.
998
   @param is_recdim Pointer that gets 1 if there is one or more record
999
   dimensions, 0 if not.
1000
1001
   @return 0 if not a record var, 1 if it is.
1002
1003
   Example use:
1004
   @code
1005
   int nrecdims;
1006
   int is_recdim[NC_MAX_VAR_DIMS];
1007
   ...
1008
   status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim);
1009
   isrecvar = (nrecdims > 0);
1010
   @endcode
1011
*/
1012
int
1013
NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim)
1014
0
{
1015
0
    int status = NC_NOERR;
1016
0
    int unlimid;
1017
0
    int nvardims;
1018
0
    int dimset[NC_MAX_VAR_DIMS];
1019
0
    int dim;
1020
0
    int nrecdims = 0;
1021
1022
0
    status = nc_inq_varndims(ncid,varid,&nvardims);
1023
0
    if(status != NC_NOERR) return status;
1024
0
    if(nvardims == 0) return NC_NOERR; /* scalars have no dims */
1025
0
    for(dim = 0; dim < nvardims; dim++)
1026
0
        is_recdim[dim] = 0;
1027
0
    status = nc_inq_unlimdim(ncid, &unlimid);
1028
0
    if(status != NC_NOERR) return status;
1029
0
    if(unlimid == -1) return status; /* no unlimited dims for any variables */
1030
0
#ifdef USE_NETCDF4
1031
0
    {
1032
0
        int nunlimdims;
1033
0
        int *unlimids;
1034
0
        int recdim;
1035
0
        status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */
1036
0
        if(status != NC_NOERR) return status;
1037
0
        if(nunlimdims == 0) return status;
1038
1039
0
        if (!(unlimids = malloc((size_t)nunlimdims * sizeof(int))))
1040
0
            return NC_ENOMEM;
1041
0
        status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */
1042
0
        if(status != NC_NOERR) {
1043
0
            free(unlimids);
1044
0
            return status;
1045
0
        }
1046
0
        status = nc_inq_vardimid(ncid, varid, dimset);
1047
0
        if(status != NC_NOERR) {
1048
0
            free(unlimids);
1049
0
            return status;
1050
0
        }
1051
0
        for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */
1052
0
            for(recdim = 0; recdim < nunlimdims; recdim++) {
1053
0
                if(dimset[dim] == unlimids[recdim]) {
1054
0
                    is_recdim[dim] = 1;
1055
0
                    nrecdims++;
1056
0
                }
1057
0
            }
1058
0
        }
1059
0
        free(unlimids);
1060
0
    }
1061
#else
1062
    status = nc_inq_vardimid(ncid, varid, dimset);
1063
    if(status != NC_NOERR) return status;
1064
    if(dimset[0] == unlimid) {
1065
        is_recdim[0] = 1;
1066
        nrecdims++;
1067
    }
1068
#endif /* USE_NETCDF4 */
1069
0
    if(nrecdimsp) *nrecdimsp = nrecdims;
1070
0
    return status;
1071
0
}
1072
1073
/* Ok to use NC pointers because
1074
   all IOSP's will use that structure,
1075
   but not ok to use e.g. NC_Var pointers
1076
   because they may be different structure
1077
   entirely.
1078
*/
1079
1080
/**
1081
   @internal
1082
   Find the length of a type. This is how much space is required by
1083
   the in memory to hold one element of this type.
1084
1085
   @param type A netCDF atomic type.
1086
1087
   @return Length of the type in bytes, or -1 if type not found.
1088
   @author Ed Hartnett
1089
*/
1090
int
1091
nctypelen(nc_type type)
1092
0
{
1093
0
    switch(type){
1094
0
    case NC_CHAR :
1095
0
        return ((int)sizeof(char));
1096
0
    case NC_BYTE :
1097
0
        return ((int)sizeof(signed char));
1098
0
    case NC_SHORT :
1099
0
        return ((int)sizeof(short));
1100
0
    case NC_INT :
1101
0
        return ((int)sizeof(int));
1102
0
    case NC_FLOAT :
1103
0
        return ((int)sizeof(float));
1104
0
    case NC_DOUBLE :
1105
0
        return ((int)sizeof(double));
1106
1107
        /* These can occur in netcdf-3 code */
1108
0
    case NC_UBYTE :
1109
0
        return ((int)sizeof(unsigned char));
1110
0
    case NC_USHORT :
1111
0
        return ((int)(sizeof(unsigned short)));
1112
0
    case NC_UINT :
1113
0
        return ((int)sizeof(unsigned int));
1114
0
    case NC_INT64 :
1115
0
        return ((int)sizeof(signed long long));
1116
0
    case NC_UINT64 :
1117
0
        return ((int)sizeof(unsigned long long));
1118
0
#ifdef USE_NETCDF4
1119
0
    case NC_STRING :
1120
0
        return ((int)sizeof(char*));
1121
0
#endif /*USE_NETCDF4*/
1122
1123
0
    default:
1124
0
        return -1;
1125
0
    }
1126
0
}
1127
1128
/**
1129
    @internal
1130
    Find the length of a type. Redundant over nctypelen() above.
1131
1132
    @param xtype an nc_type.
1133
1134
    @author Dennis Heimbigner
1135
*/
1136
size_t
1137
NC_atomictypelen(nc_type xtype)
1138
0
{
1139
0
    size_t sz = 0;
1140
0
    switch(xtype) {
1141
0
    case NC_NAT: sz = 0; break;
1142
0
    case NC_BYTE: sz = sizeof(signed char); break;
1143
0
    case NC_CHAR: sz = sizeof(char); break;
1144
0
    case NC_SHORT: sz = sizeof(short); break;
1145
0
    case NC_INT: sz = sizeof(int); break;
1146
0
    case NC_FLOAT: sz = sizeof(float); break;
1147
0
    case NC_DOUBLE: sz = sizeof(double); break;
1148
0
    case NC_INT64: sz = sizeof(signed long long); break;
1149
0
    case NC_UBYTE: sz = sizeof(unsigned char); break;
1150
0
    case NC_USHORT: sz = sizeof(unsigned short); break;
1151
0
    case NC_UINT: sz = sizeof(unsigned int); break;
1152
0
    case NC_UINT64: sz = sizeof(unsigned long long); break;
1153
0
#ifdef USE_NETCDF4
1154
0
    case NC_STRING: sz = sizeof(char*); break;
1155
0
#endif
1156
0
    default: break;
1157
0
    }
1158
0
    return sz;
1159
0
}
1160
1161
/**
1162
    @internal
1163
    Get the type name.
1164
1165
    @param xtype an nc_type.
1166
1167
    @author Dennis Heimbigner
1168
*/
1169
char *
1170
NC_atomictypename(nc_type xtype)
1171
0
{
1172
0
    char* nm = NULL;
1173
0
    switch(xtype) {
1174
0
    case NC_NAT: nm = "undefined"; break;
1175
0
    case NC_BYTE: nm = "byte"; break;
1176
0
    case NC_CHAR: nm = "char"; break;
1177
0
    case NC_SHORT: nm = "short"; break;
1178
0
    case NC_INT: nm = "int"; break;
1179
0
    case NC_FLOAT: nm = "float"; break;
1180
0
    case NC_DOUBLE: nm = "double"; break;
1181
0
    case NC_INT64: nm = "int64"; break;
1182
0
    case NC_UBYTE: nm = "ubyte"; break;
1183
0
    case NC_USHORT: nm = "ushort"; break;
1184
0
    case NC_UINT: nm = "uint"; break;
1185
0
    case NC_UINT64: nm = "uint64"; break;
1186
0
#ifdef USE_NETCDF4
1187
0
    case NC_STRING: nm = "string"; break;
1188
0
#endif
1189
0
    default: break;
1190
0
    }
1191
0
    return nm;
1192
0
}
1193
1194
/**
1195
   @internal
1196
   Get the shape of a variable.
1197
1198
   @param ncid NetCDF ID, from a previous call to nc_open() or
1199
   nc_create().
1200
   @param varid Variable ID.
1201
   @param ndims Number of dimensions for this var.
1202
   @param shape Pointer to pre-allocated array that gets the size of
1203
   each dimension.
1204
1205
   @return ::NC_NOERR No error.
1206
   @return ::NC_EBADID Bad ncid.
1207
   @return ::NC_ENOTVAR Bad varid.
1208
1209
   @author Dennis Heimbigner
1210
*/
1211
int
1212
NC_getshape(int ncid, int varid, int ndims, size_t* shape)
1213
0
{
1214
0
    int dimids[NC_MAX_VAR_DIMS];
1215
0
    int i;
1216
0
    int status = NC_NOERR;
1217
1218
0
    if ((status = nc_inq_vardimid(ncid, varid, dimids)))
1219
0
        return status;
1220
0
    for(i = 0; i < ndims; i++)
1221
0
        if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i])))
1222
0
            break;
1223
1224
0
    return status;
1225
0
}
1226
1227
/**
1228
   @internal Check the start, count, and stride parameters for gets
1229
   and puts, and handle NULLs.
1230
1231
   @param ncid The file ID.
1232
   @param varid The variable ID.
1233
   @param start Pointer to start array. If NULL ::NC_EINVALCOORDS will
1234
   be returned for non-scalar variable. This array must be same size
1235
   as variable's number of dimensions.
1236
   @param count Pointer to pointer to count array. If *count is NULL,
1237
   an array of the correct size will be allocated, and filled with
1238
   counts that represent the full extent of the variable. In this
1239
   case, the memory must be freed by the caller. If provided, this
1240
   array must be same size as variable's number of dimensions.
1241
   @param stride Pointer to pointer to stride array. If NULL, stide is
1242
   ignored. If *stride is NULL an array of the correct size will be
1243
   allocated, and filled with ones. In this case, the memory must be
1244
   freed by the caller. If provided, this
1245
   array must be same size as variable's number of dimensions.
1246
1247
   @return ::NC_NOERR No error.
1248
   @return ::NC_EBADID Bad ncid.
1249
   @return ::NC_ENOTVAR Variable not found.
1250
   @return ::NC_ENOMEM Out of memory.
1251
   @return ::NC_EINVALCOORDS Missing start array.
1252
   @author Ed Hartnett
1253
*/
1254
int
1255
NC_check_nulls(int ncid, int varid, const size_t *start, size_t **count,
1256
               ptrdiff_t **stride)
1257
0
{
1258
0
    int varndims;
1259
0
    int stat;
1260
1261
0
    if ((stat = nc_inq_varndims(ncid, varid, &varndims)))
1262
0
        return stat;
1263
1264
    /* For non-scalar vars, start is required. */
1265
0
    if (!start && varndims)
1266
0
        return NC_EINVALCOORDS;
1267
1268
    /* If count is NULL, assume full extent of var. */
1269
0
    if (!*count)
1270
0
    {
1271
0
        if (!(*count = malloc((size_t)varndims * sizeof(size_t))))
1272
0
            return NC_ENOMEM;
1273
0
        if ((stat = NC_getshape(ncid, varid, varndims, *count)))
1274
0
        {
1275
0
            free(*count);
1276
0
            *count = NULL;
1277
0
            return stat;
1278
0
        }
1279
0
    }
1280
1281
    /* If stride is NULL, do nothing, if *stride is NULL use all
1282
     * 1s. */
1283
0
    if (stride && !*stride)
1284
0
    {
1285
0
        int i;
1286
1287
0
        if (!(*stride = malloc((size_t)varndims * sizeof(ptrdiff_t))))
1288
0
            return NC_ENOMEM;
1289
0
        for (i = 0; i < varndims; i++)
1290
0
            (*stride)[i] = 1;
1291
0
    }
1292
1293
0
    return NC_NOERR;
1294
0
}
1295
1296
/**
1297
   @name Free String Resources
1298
1299
   Use these functions to free resources associated with ::NC_STRING data.
1300
*/
1301
/*! @{ */
1302
/**
1303
   Free string space allocated by the library.
1304
1305
   When you read an array string typed data the library will allocate the storage
1306
   space for the data. The allocated strings must be freed, so pass the
1307
   pointer to the array plus a count of the number of elements in the array to this function,
1308
   when you're done with the data, and it will free the allocated string memory.
1309
1310
   WARNING: This does not free the top-level array itself, only
1311
   the strings to which it points.
1312
1313
   @param len The number of character arrays in the array.
1314
   @param data The pointer to the data array.
1315
1316
   @return ::NC_NOERR No error.
1317
   @author Ed Hartnett
1318
*/
1319
int
1320
nc_free_string(size_t len, char **data)
1321
0
{
1322
0
    size_t i;
1323
0
    for (i = 0; i < len; i++)
1324
0
        free(data[i]);
1325
0
    return NC_NOERR;
1326
0
}
1327
/** @} */
1328
1329
/**
1330
   @name Variables Chunk Caches
1331
1332
   Use these functions to change the variable chunk cache settings.
1333
*/
1334
/*! @{ */
1335
/**
1336
   Change the cache settings for a chunked variable. This function allows
1337
   users to control the amount of memory used in the per-variable chunk
1338
   cache at the HDF5 level. Changing the chunk cache only has effect
1339
   until the file is closed. Once re-opened, the variable chunk cache
1340
   returns to its default value.
1341
1342
   Current cache settings for each var may be obtained with
1343
   nc_get_var_chunk_cache().
1344
1345
   Default values for these settings may be changed for the whole file
1346
   with nc_set_chunk_cache().
1347
1348
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
1349
   nc_create(), nc_def_grp(), or associated inquiry functions such as
1350
   nc_inq_ncid().
1351
   @param varid Variable ID
1352
   @param size The total size of the raw data chunk cache, in bytes.
1353
   @param nelems The number of chunk slots in the raw data chunk cache.
1354
   @param preemption The preemption, a value between 0 and 1 inclusive
1355
   that indicates how much chunks that have been fully read are favored
1356
   for preemption. A value of zero means fully read chunks are treated no
1357
   differently than other chunks (the preemption is strictly LRU) while a
1358
   value of one means fully read chunks are always preempted before other
1359
   chunks.
1360
1361
   @return ::NC_NOERR No error.
1362
   @return ::NC_EBADID Bad ncid.
1363
   @return ::NC_ENOTVAR Invalid variable ID.
1364
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
1365
   netcdf-4 file.
1366
   @return ::NC_EINVAL Invalid input
1367
1368
   @section nc_def_var_chunk_cache_example Example
1369
1370
   In this example from nc_test4/tst_coords.c, a variable is defined, and
1371
   the chunk cache settings are changed for that variable.
1372
1373
   @code
1374
   printf("**** testing setting cache values for coordinate variables...");
1375
   {
1376
   #define RANK_1 1
1377
   #define DIM0_NAME "d0"
1378
   #define CACHE_SIZE 1000000
1379
   #define CACHE_NELEMS 1009
1380
   #define CACHE_PREEMPTION .90
1381
1382
   int ncid, dimid, varid;
1383
   char name_in[NC_MAX_NAME + 1];
1384
1385
   if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
1386
   if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR;
1387
   if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR;
1388
   if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
1389
   if (nc_close(ncid)) ERR;
1390
1391
   ...
1392
   }
1393
   SUMMARIZE_ERR;
1394
   @endcode
1395
   @author Ed Hartnett
1396
*/
1397
int
1398
nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
1399
                       float preemption)
1400
0
{
1401
0
    NC* ncp;
1402
0
    int stat = NC_check_id(ncid, &ncp);
1403
0
    if(stat != NC_NOERR) return stat;
1404
0
    return ncp->dispatch->set_var_chunk_cache(ncid, varid, size,
1405
0
                                              nelems, preemption);
1406
0
}
1407
1408
/**
1409
   Get the per-variable chunk cache settings from the HDF5
1410
   layer. These settings may be changed with nc_set_var_chunk_cache().
1411
1412
   See nc_set_chunk_cache() for a full discussion of these settings.
1413
1414
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
1415
   nc_create(), nc_def_grp(), or associated inquiry functions such as
1416
   nc_inq_ncid().
1417
   @param varid Variable ID
1418
   @param sizep The total size of the raw data chunk cache, in bytes,
1419
   will be put here. @ref ignored_if_null.
1420
   @param nelemsp The number of chunk slots in the raw data chunk
1421
   cache hash table will be put here. @ref ignored_if_null.
1422
   @param preemptionp The preemption will be put here. The preemption
1423
   value is between 0 and 1 inclusive and indicates how much chunks
1424
   that have been fully read are favored for preemption. A value of
1425
   zero means fully read chunks are treated no differently than other
1426
   chunks (the preemption is strictly LRU) while a value of one means
1427
   fully read chunks are always preempted before other chunks. @ref
1428
   ignored_if_null.
1429
1430
   @return ::NC_NOERR No error.
1431
   @return ::NC_EBADID Bad ncid.
1432
   @return ::NC_ENOTVAR Invalid variable ID.
1433
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
1434
   netcdf-4 file.
1435
   @return ::NC_EINVAL Invalid input
1436
   @author Ed Hartnett
1437
*/
1438
int
1439
nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp,
1440
                       float *preemptionp)
1441
0
{
1442
0
    NC* ncp;
1443
0
    int stat = NC_check_id(ncid, &ncp);
1444
0
    if(stat != NC_NOERR) return stat;
1445
0
    return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep,
1446
0
                                              nelemsp, preemptionp);
1447
0
}
1448
1449
#ifndef USE_NETCDF4
1450
/* Make sure the fortran API is defined, even if it only returns errors */
1451
1452
int
1453
nc_set_chunk_cache_ints(int size, int nelems, int preemption)
1454
{
1455
    return NC_ENOTBUILT;
1456
}
1457
1458
int
1459
nc_get_chunk_cache_ints(int *sizep, int *nelemsp, int *preemptionp)
1460
{
1461
    return NC_ENOTBUILT;
1462
}
1463
1464
int
1465
nc_set_var_chunk_cache_ints(int ncid, int varid, int size, int nelems,
1466
          int preemption)
1467
{
1468
    return NC_ENOTBUILT;
1469
}
1470
1471
int
1472
nc_get_var_chunk_cache_ints(int ncid, int varid, int *sizep,
1473
          int *nelemsp, int *preemptionp)
1474
{
1475
    return NC_ENOTBUILT;
1476
}
1477
1478
#endif /*USE_NETCDF4*/
1479
1480
/** @} */
1481
/** @} */