Coverage Report

Created: 2023-05-28 06:42

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