Coverage Report

Created: 2025-07-23 09:13

/src/gdal/netcdf-c-4.7.4/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 @ref data_type of the variable.
152
   @param ndims Number of dimensions for the variable. For example, 2
153
   specifies a matrix, 1 specifies a vector, and 0 means the variable is
154
   a scalar with no dimensions. Must not be negative or greater than the
155
   predefined constant ::NC_MAX_VAR_DIMS. In netCDF-4/HDF5 files, may not
156
   exceed the HDF5 maximum number of dimensions (32).
157
   @param dimidsp Vector of ndims dimension IDs corresponding to the
158
   variable dimensions. For classic model netCDF files, if the ID of the
159
   unlimited dimension is included, it must be first. This argument is
160
   ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there
161
   may be any number of unlimited dimensions, and they may be used in any
162
   element of the dimids array.
163
   @param varidp Pointer to location for the returned variable ID.
164
165
   @return ::NC_NOERR No error.
166
   @return ::NC_EBADID Bad ncid.
167
   @return ::NC_ENOTINDEFINE Not in define mode.
168
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
169
   @return ::NC_EMAXVARS NC_MAX_VARS exceeded [Not enforced after 4.5.0]
170
   @return ::NC_EBADTYPE Bad type.
171
   @return ::NC_EINVAL Invalid input.
172
   @return ::NC_ENAMEINUSE Name already in use.
173
   @return ::NC_EPERM Attempt to create object in read-only file.
174
175
   @section nc_def_var_example Example
176
177
   Here is an example using nc_def_var to create a variable named rh of
178
   type double with three dimensions, time, lat, and lon in a new netCDF
179
   dataset named foo.nc:
180
181
   @code
182
   #include <netcdf.h>
183
   ...
184
   int  status;
185
   int  ncid;
186
   int  lat_dim, lon_dim, time_dim;
187
   int  rh_id;
188
   int  rh_dimids[3];
189
   ...
190
   status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
191
   if (status != NC_NOERR) handle_error(status);
192
   ...
193
194
   status = nc_def_dim(ncid, "lat", 5L, &lat_dim);
195
   if (status != NC_NOERR) handle_error(status);
196
   status = nc_def_dim(ncid, "lon", 10L, &lon_dim);
197
   if (status != NC_NOERR) handle_error(status);
198
   status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
199
   if (status != NC_NOERR) handle_error(status);
200
   ...
201
202
   rh_dimids[0] = time_dim;
203
   rh_dimids[1] = lat_dim;
204
   rh_dimids[2] = lon_dim;
205
   status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id);
206
   if (status != NC_NOERR) handle_error(status);
207
   @endcode
208
209
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
210
*/
211
int
212
nc_def_var(int ncid, const char *name, nc_type xtype,
213
           int ndims,  const int *dimidsp, int *varidp)
214
150k
{
215
150k
    NC* ncp;
216
150k
    int stat = NC_NOERR;
217
218
150k
    if ((stat = NC_check_id(ncid, &ncp)))
219
0
        return stat;
220
150k
    TRACE(nc_def_var);
221
150k
    return ncp->dispatch->def_var(ncid, name, xtype, ndims,
222
150k
                                  dimidsp, varidp);
223
150k
}
224
225
/**
226
   Set the fill value for a variable.
227
228
   @note For netCDF classic, 64-bit offset, and CDF5 formats, it is
229
   allowed (but not good practice) to set the fill value after data
230
   have been written to the variable. In this case, unless the
231
   variable has been completely specified (without gaps in the data),
232
   any existing filled values will not be recognized as fill values by
233
   applications reading the data. Best practice is to set the fill
234
   value after the variable has been defined, but before any data have
235
   been written to that variable. In NetCDF-4 files, this is enforced
236
   by the HDF5 library. For netCDF-4 files, an error is returned if
237
   the user attempts to set the fill value after writing data to the
238
   variable.
239
240
   @param ncid NetCDF ID, from a previous call to nc_open() or
241
   nc_create().
242
   @param varid Variable ID.
243
   @param no_fill Set to ::NC_NOFILL to turn off fill mode for this
244
   variable. Set to ::NC_FILL (the default) to turn on fill mode for
245
   the variable.
246
   @param fill_value the fill value to be used for this variable. Must
247
   be the same type as the variable. This must point to enough free
248
   memory to hold one element of the data type of the variable. (For
249
   example, an ::NC_INT will require 4 bytes for it's fill value,
250
   which is also an ::NC_INT.)
251
252
   @return ::NC_NOERR No error.
253
   @return ::NC_EBADID Bad ID.
254
   @return ::NC_ENOTINDEFINE Not in define mode.  This is returned for
255
   netCDF classic, 64-bit offset, or 64-bit data files, or for
256
   netCDF-4 files, when they were created with ::NC_CLASSIC_MODEL flag by
257
   nc_creae().
258
   @return ::NC_EPERM Attempt to create object in read-only file.
259
   @return ::NC_ELATEDEF (NetCDF-4 only). Returned when user attempts
260
   to set fill value after data are written.
261
   @return ::NC_EGLOBAL Attempt to set fill value on NC_GLOBAL.
262
263
   @section nc_def_var_fill_example Example
264
265
   In this example from libsrc4/tst_vars.c, a variable is defined, and
266
   the fill mode turned off. Then nc_inq_fill() is used to check that
267
   the setting is correct. Then some data are written to the
268
   variable. Since the data that are written do not cover the full
269
   extent of the variable, the missing values will just be random. If
270
   fill value mode was turned on, the missing values would get the
271
   fill value.
272
273
   @code
274
   #define DIM7_LEN 2
275
   #define DIM7_NAME "dim_7_from_Indiana"
276
   #define VAR7_NAME "var_7_from_Idaho"
277
   #define NDIMS 1
278
   int dimids[NDIMS];
279
   size_t index[NDIMS];
280
   int varid;
281
   int no_fill;
282
   unsigned short ushort_data = 42, ushort_data_in, fill_value_in;
283
284
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
285
   if (nc_def_dim(ncid, DIM7_NAME, DIM7_LEN, &dimids[0])) ERR;
286
   if (nc_def_var(ncid, VAR7_NAME, NC_USHORT, NDIMS, dimids,
287
   &varid)) ERR;
288
   if (nc_def_var_fill(ncid, varid, 1, NULL)) ERR;
289
290
   if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR;
291
   if (!no_fill) ERR;
292
293
   index[0] = 1;
294
   if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR;
295
296
   index[0] = 0;
297
   if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR;
298
299
   if (nc_close(ncid)) ERR;
300
   @endcode
301
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
302
*/
303
int
304
nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
305
0
{
306
0
    NC* ncp;
307
0
    int stat = NC_check_id(ncid,&ncp);
308
0
    if(stat != NC_NOERR) return stat;
309
310
    /* Using NC_GLOBAL is illegal, as this API has no provision for
311
     * specifying the type of the fillvalue, it must of necessity be
312
     * using the type of the variable to interpret the bytes of the
313
     * fill_value argument. */
314
0
    if (varid == NC_GLOBAL) return NC_EGLOBAL;
315
316
0
    return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
317
0
}
318
319
/**
320
   Set the zlib compression settings for a netCDF-4/HDF5 variable.
321
322
   This function must be called after nc_def_var and before nc_enddef
323
   or any functions which writes data to the file.
324
325
   Deflation and shuffline require chunked data. If this function is
326
   called on a variable with contiguous data, then the data is changed
327
   to chunked data, with default chunksizes. Use nc_def_var_chunking()
328
   to tune performance with user-defined chunksizes.
329
330
   If this function is called on a scalar variable, ::NC_EINVAL is
331
   returned. Only chunked variables may use filters.
332
333
   If this function is called on a variable which already has szip
334
   compression turned on, ::NC_EINVAL is returned.
335
336
   @note Parallel I/O reads work with compressed data. Parallel I/O
337
   writes work with compressed data in netcdf-c-4.7.4 and later
338
   releases, using hdf5-1.10.3 and later releases. Using the zlib,
339
   shuffle (or any other) filter requires that collective access be
340
   used with the variable. Turning on deflate and/or shuffle for a
341
   variable in a file opened for parallel I/O will automatically
342
   switch the access for that variable to collective access.
343
344
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
345
   nc_create(), nc_def_grp(), or associated inquiry functions such as
346
   nc_inq_ncid().
347
   @param varid Variable ID
348
   @param shuffle True to turn on the shuffle filter. The shuffle
349
   filter can assist with the compression of data by changing the byte
350
   order in the data stream. It makes no sense to use the shuffle
351
   filter without setting a deflate level.
352
   @param deflate True to turn on deflation for this variable.
353
   @param deflate_level A number between 0 (no compression) and 9
354
   (maximum compression).
355
356
   @return ::NC_NOERR No error.
357
   @return ::NC_EBADID Bad ncid.
358
   @return ::NC_ENOTVAR Invalid variable ID.
359
   @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
360
   not netCDF-4/HDF5.
361
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
362
   netcdf-4 file.
363
   @return ::NC_ELATEDEF Too late to change settings for this variable.
364
   @return ::NC_ENOTINDEFINE Not in define mode.
365
   @return ::NC_EPERM File is read only.
366
   @return ::NC_ESTRICTNC3 Attempting to create netCDF-4 type var in
367
   classic model file
368
   @return ::NC_EHDFERR Error returned by HDF5 layer.
369
   @return ::NC_EINVAL Invalid input. Deflate can't be set unless
370
   variable storage is NC_CHUNK.
371
372
   @section nc_def_var_deflate_example Example
373
374
   Here is an example from /examples/C/simple_xy_nc4_wr.c using
375
   nc_def_var_deflate to create a variable and then turn on the shuffle
376
   filter and compression.
377
378
   @code
379
   #include <netcdf.h>
380
   #define NDIMS 2
381
   #define NX 6
382
   #define NY 12
383
384
   int ncid, x_dimid, y_dimid, varid;
385
   int dimids[NDIMS];
386
   int shuffle, deflate, deflate_level;
387
   int data_out[NX][NY];
388
   int x, y, retval;
389
390
   shuffle = NC_SHUFFLE;
391
   deflate = 1;
392
   deflate_level = 1;
393
   ...
394
   if ((retval = nc_create(FILE_NAME, NC_NETCDF4, &ncid)))
395
   ERR(retval);
396
397
   if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid)))
398
   ERR(retval);
399
   if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid)))
400
   ERR(retval);
401
402
   dimids[0] = x_dimid;
403
   dimids[1] = y_dimid;
404
405
   if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS,
406
   dimids, &varid)))
407
   ERR(retval);
408
409
   ...
410
411
   if ((retval = nc_def_var_deflate(ncid, varid, shuffle, deflate,
412
   deflate_level)))
413
   ERR(retval);
414
   ...
415
   @endcode
416
   @author Ed Hartnett, Dennis Heimbigner
417
*/
418
int
419
nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level)
420
0
{
421
0
    NC* ncp;
422
0
    int stat = NC_check_id(ncid,&ncp);
423
0
    if(stat != NC_NOERR) return stat;
424
0
    return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level);
425
0
}
426
427
/**
428
   Set checksum for a var.
429
430
   This function must be called after nc_def_var and before nc_enddef
431
   or any functions which writes data to the file.
432
433
   Checksums require chunked data. If this function is called on a
434
   variable with contiguous data, then the data is changed to chunked
435
   data, with default chunksizes. Use nc_def_var_chunking() to tune
436
   performance with user-defined chunksizes.
437
438
   @note Parallel I/O reads work with fletcher32 encoded
439
   data. Parallel I/O writes work with fletcher32 in netcdf-c-4.7.4
440
   and later releases, using hdf5-1.10.2 and later releases. Using the
441
   fletcher32 (or any) filter requires that collective access be used
442
   with the variable. Turning on fletcher32 for a variable in a file
443
   opened for parallel I/O will automatically switch the access for
444
   that variable to collective access.
445
446
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
447
   nc_create(), nc_def_grp(), or associated inquiry functions such as
448
   nc_inq_ncid().
449
   @param varid Variable ID
450
   @param fletcher32 True to turn on Fletcher32 checksums for this
451
   variable.
452
453
   @return ::NC_NOERR No error.
454
   @return ::NC_EBADID Bad ncid.
455
   @return ::NC_ENOTVAR Invalid variable ID.
456
   @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
457
   not netCDF-4/HDF5.
458
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
459
   netcdf-4 file.
460
   @return ::NC_ELATEDEF Too late to change settings for this variable.
461
   @return ::NC_EINVAL Invalid input
462
   @author Ed Hartnett, Dennis Heimbigner
463
*/
464
int
465
nc_def_var_fletcher32(int ncid, int varid, int fletcher32)
466
0
{
467
0
    NC* ncp;
468
0
    int stat = NC_check_id(ncid,&ncp);
469
0
    if(stat != NC_NOERR) return stat;
470
0
    return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32);
471
0
}
472
473
/**
474
   Define storage and, if chunked storage is used, chunking parameters
475
   for a variable
476
477
   The storage may be set to NC_CONTIGUOUS, NC_COMPACT, or NC_CHUNKED.
478
479
   Contiguous storage means the variable is stored as one block of
480
   data in the file. This is the default storage.
481
482
   Compact storage means the variable is stored in the header record
483
   of the file. This can have large performance benefits on HPC system
484
   running many processors. Compact storage is only available for
485
   variables whose data are 64 KB or less. Attempting to turn on
486
   compact storage for a variable that is too large will result in the
487
   ::NC_EVARSIZE error.
488
489
   Chunked storage means the data are stored as chunks, of
490
   user-configurable size. Chunked storage is required for variable
491
   with one or more unlimted dimensions, or variable which use
492
   compression, or any other filter.
493
494
   The total size of a chunk must be less than 4 GiB. That is, the
495
   product of all chunksizes and the size of the data (or the size of
496
   nc_vlen_t for VLEN types) must be less than 4 GiB.
497
498
   This function may only be called after the variable is defined, but
499
   before nc_enddef is called. Once the chunking parameters are set for a
500
   variable, they cannot be changed.
501
502
   @note Scalar variables may have a storage of NC_CONTIGUOUS or
503
   NC_COMPACT. Attempts to set chunking on a scalare variable will
504
   cause ::NC_EINVEL to be returned. Only non-scalar variables can
505
   have chunking.
506
507
   @param ncid NetCDF ID, from a previous call to nc_open() or
508
   nc_create().
509
   @param varid Variable ID.
510
   @param storage If ::NC_CONTIGUOUS or ::NC_COMPACT, then contiguous
511
   or compact storage is used for this variable. Variables with one or
512
   more unlimited dimensions cannot use contiguous or compact
513
   storage. If contiguous or compact storage is turned on, the
514
   chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked
515
   storage is used for this variable. Chunk sizes may be specified
516
   with the chunksizes parameter or default sizes will be used if that
517
   parameter is NULL.
518
   @param chunksizesp A pointer to an array list of chunk sizes. The
519
   array must have one chunksize for each dimension of the variable. If
520
   ::NC_CONTIGUOUS storage is set, then the chunksizes parameter is
521
   ignored. Ignored if NULL.
522
523
   @return ::NC_NOERR No error.
524
   @return ::NC_EBADID Bad ID.
525
   @return ::NC_ENOTNC4 Not a netCDF-4 file.
526
   @return ::NC_ELATEDEF This variable has already been the subject of
527
   a nc_enddef call.  In netCDF-4 files nc_enddef will be called
528
   automatically for any data read or write. Once nc_enddef has been
529
   called after the nc_def_var call for a variable, it is impossible
530
   to set the chunking for that variable.
531
   @return ::NC_ENOTINDEFINE Not in define mode.  This is returned for
532
   netCDF classic or 64-bit offset files, or for netCDF-4 files, when
533
   they wwere created with ::NC_CLASSIC_MODEL flag by nc_create().
534
   @return ::NC_EPERM Attempt to create object in read-only file.
535
   @return ::NC_EBADCHUNK Returns if the chunk size specified for a
536
   variable is larger than the length of the dimensions associated with
537
   variable.
538
   @return ::NC_EVARSIZE Compact storage attempted for variable bigger
539
   than 64 KB.
540
   @return ::NC_EINVAL Attempt to set contiguous or compact storage
541
   for var with one or more unlimited dimensions, or chunking for a
542
   scalar var.
543
544
   @section nc_def_var_chunking_example Example
545
546
   In this example from libsrc4/tst_vars2.c, chunksizes are set with
547
   nc_var_def_chunking, and checked with nc_var_inq_chunking.
548
549
   @code
550
   printf("**** testing chunking...");
551
   {
552
   #define NDIMS5 1
553
   #define DIM5_NAME "D5"
554
   #define VAR_NAME5 "V5"
555
   #define DIM5_LEN 1000
556
557
   int dimids[NDIMS5], dimids_in[NDIMS5];
558
   int varid;
559
   int ndims, nvars, natts, unlimdimid;
560
   nc_type xtype_in;
561
   char name_in[NC_MAX_NAME + 1];
562
   int data[DIM5_LEN], data_in[DIM5_LEN];
563
   size_t chunksize[NDIMS5] = {5};
564
   size_t chunksize_in[NDIMS5];
565
   int storage_in;
566
   int i, d;
567
568
   for (i = 0; i < DIM5_LEN; i++)
569
   data[i] = i;
570
571
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
572
   if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR;
573
   if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR;
574
   if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR;
575
   if (nc_put_var_int(ncid, varid, data)) ERR;
576
577
   if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR;
578
   for (d = 0; d < NDIMS5; d++)
579
   if (chunksize[d] != chunksize_in[d]) ERR;
580
   if (storage_in != NC_CHUNKED) ERR;
581
   @endcode
582
   @author Ed Hartnett, Dennis Heimbigner
583
*/
584
int
585
nc_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp)
586
0
{
587
0
    NC* ncp;
588
0
    int stat = NC_check_id(ncid, &ncp);
589
0
    if(stat != NC_NOERR) return stat;
590
0
    return ncp->dispatch->def_var_chunking(ncid, varid, storage,
591
0
                                           chunksizesp);
592
0
}
593
594
/**
595
   Define endianness of a variable.
596
597
   With this function the endianness (i.e. order of bits in integers) can
598
   be changed on a per-variable basis. By default, the endianness is the
599
   same as the default endianness of the platform. But with
600
   nc_def_var_endianness the endianness can be explicitly set for a
601
   variable.
602
603
   Warning: this function is only defined if the type of the variable
604
   is an atomic integer or float type.
605
606
   This function may only be called after the variable is defined, but
607
   before nc_enddef is called.
608
609
   @param ncid NetCDF ID, from a previous call to nc_open() or
610
   nc_create().
611
612
   @param varid Variable ID.
613
614
   @param endian ::NC_ENDIAN_NATIVE to select the native endianness of
615
   the platform (the default), ::NC_ENDIAN_LITTLE to use
616
   little-endian, ::NC_ENDIAN_BIG to use big-endian.
617
618
   @return ::NC_NOERR No error.
619
   @return ::NC_EBADID Bad ID.
620
   @return ::NC_ENOTNC4 Not a netCDF-4 file.
621
   @return ::NC_ELATEDEF This variable has already been the subject of a
622
   nc_enddef call. In netCDF-4 files nc_enddef will be called
623
   automatically for any data read or write. Once nc_enddef has been
624
   called after the nc_def_var call for a variable, it is impossible to
625
   set the chunking for that variable.
626
   @return ::NC_ENOTINDEFINE Not in define mode. This is returned for
627
   netCDF classic or 64-bit offset files, or for netCDF-4 files, when
628
   they wwere created with ::NC_CLASSIC_MODEL flag by nc_create().
629
   @return ::NC_EPERM Attempt to create object in read-only file.
630
631
   @section nc_def_var_endian_example Example
632
633
   In this example from libsrc4/tst_vars2.c, a variable is created, and
634
   the endianness set to ::NC_ENDIAN_BIG.
635
636
   @code
637
   #define NDIMS4 1
638
   #define DIM4_NAME "Joe"
639
   #define VAR_NAME4 "Ed"
640
   #define DIM4_LEN 10
641
   {
642
   int dimids[NDIMS4], dimids_in[NDIMS4];
643
   int varid;
644
   int ndims, nvars, natts, unlimdimid;
645
   nc_type xtype_in;
646
   char name_in[NC_MAX_NAME + 1];
647
   int data[DIM4_LEN], data_in[DIM4_LEN];
648
   int endian_in;
649
   int i;
650
651
   for (i = 0; i < DIM4_LEN; i++)
652
   data[i] = i;
653
654
   if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
655
   if (nc_def_dim(ncid, DIM4_NAME, DIM4_LEN, &dimids[0])) ERR;
656
   if (dimids[0] != 0) ERR;
657
   if (nc_def_var(ncid, VAR_NAME4, NC_INT, NDIMS4, dimids, &varid)) ERR;
658
   if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) ERR;
659
   @endcode
660
   @author Ed Hartnett
661
*/
662
int
663
nc_def_var_endian(int ncid, int varid, int endian)
664
0
{
665
0
    NC* ncp;
666
0
    int stat = NC_check_id(ncid,&ncp);
667
0
    if(stat != NC_NOERR) return stat;
668
0
    return ncp->dispatch->def_var_endian(ncid,varid,endian);
669
0
}
670
671
/**
672
 * Set szip compression settings on a variable. Szip is an
673
 * implementation of the extended-Rice lossless compression algorithm;
674
 * it is reported to provide fast and effective compression. Szip is
675
 * only available to netCDF if HDF5 was built with szip support.
676
 *
677
 * SZIP compression cannot be applied to variables with any
678
 * user-defined type.
679
 *
680
 * If zlib compression has already be turned on for a variable, then
681
 * this function will return ::NC_EINVAL.
682
 *
683
 * To learn the szip settings for a variable, use nc_inq_var_szip().
684
 *
685
 * @note The options_mask parameter may be either NC_SZIP_EC (entropy
686
 * coding) or NC_SZIP_NN (nearest neighbor):
687
 * * The entropy coding method is best suited for data that has been
688
 * processed. The EC method works best for small numbers.
689
 * * The nearest neighbor coding method preprocesses the data then the
690
 * applies EC method as above.
691
 *
692
 * For more information about HDF5 and szip, see
693
 * https://support.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSzip
694
 * and
695
 * https://support.hdfgroup.org/doc_resource/SZIP/index.html.
696
 *
697
 * @param ncid File ID.
698
 * @param varid Variable ID.
699
 * @param options_mask The options mask. Can be NC_SZIP_EC or
700
 * NC_SZIP_NN.
701
 * @param pixels_per_block Pixels per block. Must be even and not
702
 * greater than 32, with typical values being 8, 10, 16, or 32. This
703
 * parameter affects compression ratio; the more pixel values vary,
704
 * the smaller this number should be to achieve better performance. If
705
 * pixels_per_block is bigger than the total number of elements in a
706
 * dataset chunk, ::NC_EINVAL will be returned.
707
 *
708
 * @returns ::NC_NOERR No error.
709
 * @returns ::NC_EBADID Bad ncid.
710
 * @returns ::NC_ENOTVAR Invalid variable ID.
711
 * @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is
712
 * not netCDF-4/HDF5.
713
 * @returns ::NC_ELATEDEF Too late to change settings for this variable.
714
 * @returns ::NC_ENOTINDEFINE Not in define mode.
715
 * @returns ::NC_EINVAL Invalid input, or zlib filter already applied
716
 * to this var.
717
 * @author Ed Hartnett
718
 */
719
int
720
nc_def_var_szip(int ncid, int varid, int options_mask, int pixels_per_block)
721
0
{
722
0
    int ret;
723
724
    /* This will cause H5Pset_szip to be called when the var is
725
     * created. */
726
0
    unsigned int params[2];
727
0
    params[0] = options_mask;
728
0
    params[1] = pixels_per_block;
729
0
    if ((ret = nc_def_var_filter(ncid, varid, HDF5_FILTER_SZIP, 2, params)))
730
0
        return ret;
731
732
0
    return NC_NOERR;
733
0
}
734
735
/** @} */
736
737
/**
738
   @name Rename a Variable
739
740
   Rename a variable.
741
*/
742
/** @{ */
743
744
/**
745
   Rename a variable.
746
747
   This function changes the name of a netCDF variable in an open netCDF
748
   file or group. You cannot rename a variable to have the name of any existing
749
   variable.
750
751
   For classic format, 64-bit offset format, and netCDF-4/HDF5 with
752
   classic mode, if the new name is longer than the old name, the netCDF
753
   dataset must be in define mode.
754
755
   For netCDF-4/HDF5 files, renaming the variable changes the order of
756
   the variables in the file. The renamed variable becomes the last
757
   variable in the file.
758
759
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
760
   nc_create(), nc_def_grp(), or associated inquiry functions such as
761
   nc_inq_ncid().
762
763
   @param varid Variable ID
764
765
   @param name New name of the variable.
766
767
   @return ::NC_NOERR No error.
768
   @return ::NC_EBADID Bad ncid.
769
   @return ::NC_ENOTVAR Invalid variable ID.
770
   @return ::NC_EBADNAME Bad name.
771
   @return ::NC_EMAXNAME Name is too long.
772
   @return ::NC_ENAMEINUSE Name in use.
773
   @return ::NC_ENOMEM Out of memory.
774
775
   @section nc_rename_var_example Example
776
777
   Here is an example using nc_rename_var to rename the variable rh to
778
   rel_hum in an existing netCDF dataset named foo.nc:
779
780
   @code
781
   #include <netcdf.h>
782
   ...
783
   int  status;
784
   int  ncid;
785
   int  rh_id;
786
   ...
787
   status = nc_open("foo.nc", NC_WRITE, &ncid);
788
   if (status != NC_NOERR) handle_error(status);
789
   ...
790
   status = nc_redef(ncid);
791
   if (status != NC_NOERR) handle_error(status);
792
   status = nc_inq_varid (ncid, "rh", &rh_id);
793
   if (status != NC_NOERR) handle_error(status);
794
   status = nc_rename_var (ncid, rh_id, "rel_hum");
795
   if (status != NC_NOERR) handle_error(status);
796
   status = nc_enddef(ncid);
797
   if (status != NC_NOERR) handle_error(status);
798
   @endcode
799
   @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
800
*/
801
int
802
nc_rename_var(int ncid, int varid, const char *name)
803
0
{
804
0
    NC* ncp;
805
0
    int stat = NC_check_id(ncid, &ncp);
806
0
    if(stat != NC_NOERR) return stat;
807
0
    TRACE(nc_rename_var);
808
0
    return ncp->dispatch->rename_var(ncid, varid, name);
809
0
}
810
/** @} */
811
812
/**
813
   @internal Does a variable have a record dimension?
814
815
   @param ncid File ID.
816
   @param varid Variable ID.
817
   @param nrecs Pointer that gets number of records.
818
819
   @return 0 if not a record var, 1 if it is.
820
*/
821
int
822
NC_is_recvar(int ncid, int varid, size_t* nrecs)
823
0
{
824
0
    int status = NC_NOERR;
825
0
    int unlimid;
826
0
    int ndims;
827
0
    int dimset[NC_MAX_VAR_DIMS];
828
829
0
    status = nc_inq_unlimdim(ncid,&unlimid);
830
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
831
0
    status = nc_inq_varndims(ncid,varid,&ndims);
832
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
833
0
    if(ndims == 0) return 0; /* scalar */
834
0
    status = nc_inq_vardimid(ncid,varid,dimset);
835
0
    if(status != NC_NOERR) return 0; /* no unlimited defined */
836
0
    status = nc_inq_dim(ncid,dimset[0],NULL,nrecs);
837
0
    if(status != NC_NOERR) return 0;
838
0
    return (dimset[0] == unlimid ? 1: 0);
839
0
}
840
841
/**
842
   @internal Get the number of record dimensions for a variable and an
843
   array that identifies which of a variable's dimensions are record
844
   dimensions. Intended to be used instead of NC_is_recvar(), which
845
   doesn't work for netCDF-4 variables which have multiple unlimited
846
   dimensions or an unlimited dimension that is not the first of a
847
   variable's dimensions.
848
849
   @param ncid File ID.
850
   @param varid Variable ID.
851
   @param nrecdimsp Pointer that gets number of record dims.
852
   @param is_recdim Pointer that gets 1 if there is one or more record
853
   dimensions, 0 if not.
854
855
   @return 0 if not a record var, 1 if it is.
856
857
   Example use:
858
   @code
859
   int nrecdims;
860
   int is_recdim[NC_MAX_VAR_DIMS];
861
   ...
862
   status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim);
863
   isrecvar = (nrecdims > 0);
864
   @endcode
865
*/
866
int
867
NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim)
868
0
{
869
0
    int status = NC_NOERR;
870
0
    int unlimid;
871
0
    int nvardims;
872
0
    int dimset[NC_MAX_VAR_DIMS];
873
0
    int dim;
874
0
    int nrecdims = 0;
875
876
0
    status = nc_inq_varndims(ncid,varid,&nvardims);
877
0
    if(status != NC_NOERR) return status;
878
0
    if(nvardims == 0) return NC_NOERR; /* scalars have no dims */
879
0
    for(dim = 0; dim < nvardims; dim++)
880
0
        is_recdim[dim] = 0;
881
0
    status = nc_inq_unlimdim(ncid, &unlimid);
882
0
    if(status != NC_NOERR) return status;
883
0
    if(unlimid == -1) return status; /* no unlimited dims for any variables */
884
0
#ifdef USE_NETCDF4
885
0
    {
886
0
        int nunlimdims;
887
0
        int *unlimids;
888
0
        int recdim;
889
0
        status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */
890
0
        if(status != NC_NOERR) return status;
891
0
        if(nunlimdims == 0) return status;
892
893
0
        if (!(unlimids = malloc(nunlimdims * sizeof(int))))
894
0
            return NC_ENOMEM;
895
0
        status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */
896
0
        if(status != NC_NOERR) {
897
0
            free(unlimids);
898
0
            return status;
899
0
        }
900
0
        status = nc_inq_vardimid(ncid, varid, dimset);
901
0
        if(status != NC_NOERR) {
902
0
            free(unlimids);
903
0
            return status;
904
0
        }
905
0
        for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */
906
0
            for(recdim = 0; recdim < nunlimdims; recdim++) {
907
0
                if(dimset[dim] == unlimids[recdim]) {
908
0
                    is_recdim[dim] = 1;
909
0
                    nrecdims++;
910
0
                }
911
0
            }
912
0
        }
913
0
        free(unlimids);
914
0
    }
915
#else
916
    status = nc_inq_vardimid(ncid, varid, dimset);
917
    if(status != NC_NOERR) return status;
918
    if(dimset[0] == unlimid) {
919
        is_recdim[0] = 1;
920
        nrecdims++;
921
    }
922
#endif /* USE_NETCDF4 */
923
0
    if(nrecdimsp) *nrecdimsp = nrecdims;
924
0
    return status;
925
0
}
926
927
/* Ok to use NC pointers because
928
   all IOSP's will use that structure,
929
   but not ok to use e.g. NC_Var pointers
930
   because they may be different structure
931
   entirely.
932
*/
933
934
/**
935
   @internal
936
   Find the length of a type. This is how much space is required by
937
   the in memory to hold one element of this type.
938
939
   @param type A netCDF atomic type.
940
941
   @return Length of the type in bytes, or -1 if type not found.
942
   @author Ed Hartnett
943
*/
944
int
945
nctypelen(nc_type type)
946
3.24M
{
947
3.24M
    switch(type){
948
1.81M
    case NC_CHAR :
949
1.81M
        return ((int)sizeof(char));
950
1.36M
    case NC_BYTE :
951
1.36M
        return ((int)sizeof(signed char));
952
0
    case NC_SHORT :
953
0
        return ((int)sizeof(short));
954
37.9k
    case NC_INT :
955
37.9k
        return ((int)sizeof(int));
956
10.4k
    case NC_FLOAT :
957
10.4k
        return ((int)sizeof(float));
958
17.7k
    case NC_DOUBLE :
959
17.7k
        return ((int)sizeof(double));
960
961
        /* These can occur in netcdf-3 code */
962
2.08k
    case NC_UBYTE :
963
2.08k
        return ((int)sizeof(unsigned char));
964
0
    case NC_USHORT :
965
0
        return ((int)(sizeof(unsigned short)));
966
0
    case NC_UINT :
967
0
        return ((int)sizeof(unsigned int));
968
0
    case NC_INT64 :
969
0
        return ((int)sizeof(signed long long));
970
0
    case NC_UINT64 :
971
0
        return ((int)sizeof(unsigned long long));
972
0
#ifdef USE_NETCDF4
973
0
    case NC_STRING :
974
0
        return ((int)sizeof(char*));
975
0
#endif /*USE_NETCDF4*/
976
977
0
    default:
978
0
        return -1;
979
3.24M
    }
980
3.24M
}
981
982
/**
983
    @internal
984
    Find the length of a type. Redundant over nctypelen() above.
985
986
    @param xtype an nc_type.
987
988
    @author Dennis Heimbigner
989
*/
990
size_t
991
NC_atomictypelen(nc_type xtype)
992
0
{
993
0
    size_t sz = 0;
994
0
    switch(xtype) {
995
0
    case NC_NAT: sz = 0; break;
996
0
    case NC_BYTE: sz = sizeof(signed char); break;
997
0
    case NC_CHAR: sz = sizeof(char); break;
998
0
    case NC_SHORT: sz = sizeof(short); break;
999
0
    case NC_INT: sz = sizeof(int); break;
1000
0
    case NC_FLOAT: sz = sizeof(float); break;
1001
0
    case NC_DOUBLE: sz = sizeof(double); break;
1002
0
    case NC_INT64: sz = sizeof(signed long long); break;
1003
0
    case NC_UBYTE: sz = sizeof(unsigned char); break;
1004
0
    case NC_USHORT: sz = sizeof(unsigned short); break;
1005
0
    case NC_UINT: sz = sizeof(unsigned int); break;
1006
0
    case NC_UINT64: sz = sizeof(unsigned long long); break;
1007
0
#ifdef USE_NETCDF4
1008
0
    case NC_STRING: sz = sizeof(char*); break;
1009
0
#endif
1010
0
    default: break;
1011
0
    }
1012
0
    return sz;
1013
0
}
1014
1015
/**
1016
    @internal
1017
    Get the type name.
1018
1019
    @param xtype an nc_type.
1020
1021
    @author Dennis Heimbigner
1022
*/
1023
char *
1024
NC_atomictypename(nc_type xtype)
1025
0
{
1026
0
    char* nm = NULL;
1027
0
    switch(xtype) {
1028
0
    case NC_NAT: nm = "undefined"; break;
1029
0
    case NC_BYTE: nm = "byte"; break;
1030
0
    case NC_CHAR: nm = "char"; break;
1031
0
    case NC_SHORT: nm = "short"; break;
1032
0
    case NC_INT: nm = "int"; break;
1033
0
    case NC_FLOAT: nm = "float"; break;
1034
0
    case NC_DOUBLE: nm = "double"; break;
1035
0
    case NC_INT64: nm = "int64"; break;
1036
0
    case NC_UBYTE: nm = "ubyte"; break;
1037
0
    case NC_USHORT: nm = "ushort"; break;
1038
0
    case NC_UINT: nm = "uint"; break;
1039
0
    case NC_UINT64: nm = "uint64"; break;
1040
0
#ifdef USE_NETCDF4
1041
0
    case NC_STRING: nm = "string"; break;
1042
0
#endif
1043
0
    default: break;
1044
0
    }
1045
0
    return nm;
1046
0
}
1047
1048
/**
1049
   @internal
1050
   Get the shape of a variable.
1051
1052
   @param ncid NetCDF ID, from a previous call to nc_open() or
1053
   nc_create().
1054
   @param varid Variable ID.
1055
   @param ndims Number of dimensions for this var.
1056
   @param shape Pointer to pre-allocated array that gets the size of
1057
   each dimension.
1058
1059
   @return ::NC_NOERR No error.
1060
   @return ::NC_EBADID Bad ncid.
1061
   @return ::NC_ENOTVAR Bad varid.
1062
1063
   @author Dennis Heimbigner
1064
*/
1065
int
1066
NC_getshape(int ncid, int varid, int ndims, size_t* shape)
1067
0
{
1068
0
    int dimids[NC_MAX_VAR_DIMS];
1069
0
    int i;
1070
0
    int status = NC_NOERR;
1071
1072
0
    if ((status = nc_inq_vardimid(ncid, varid, dimids)))
1073
0
        return status;
1074
0
    for(i = 0; i < ndims; i++)
1075
0
        if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i])))
1076
0
            break;
1077
1078
0
    return status;
1079
0
}
1080
1081
/**
1082
   @internal Check the start, count, and stride parameters for gets
1083
   and puts, and handle NULLs.
1084
1085
   @param ncid The file ID.
1086
   @param varid The variable ID.
1087
   @param start Pointer to start array. If NULL ::NC_EINVALCOORDS will
1088
   be returned for non-scalar variable.
1089
   @param count Pointer to pointer to count array. If *count is NULL,
1090
   an array of the correct size will be allocated, and filled with
1091
   counts that represent the full extent of the variable. In this
1092
   case, the memory must be freed by the caller.
1093
   @param stride Pointer to pointer to stride array. If NULL, stide is
1094
   ignored. If *stride is NULL an array of the correct size will be
1095
   allocated, and filled with ones. In this case, the memory must be
1096
   freed by the caller.
1097
1098
   @return ::NC_NOERR No error.
1099
   @return ::NC_EBADID Bad ncid.
1100
   @return ::NC_ENOTVAR Variable not found.
1101
   @return ::NC_ENOMEM Out of memory.
1102
   @return ::NC_EINVALCOORDS Missing start array.
1103
   @author Ed Hartnett
1104
*/
1105
int
1106
NC_check_nulls(int ncid, int varid, const size_t *start, size_t **count,
1107
               ptrdiff_t **stride)
1108
0
{
1109
0
    int varndims;
1110
0
    int stat;
1111
1112
0
    if ((stat = nc_inq_varndims(ncid, varid, &varndims)))
1113
0
        return stat;
1114
1115
    /* For non-scalar vars, start is required. */
1116
0
    if (!start && varndims)
1117
0
        return NC_EINVALCOORDS;
1118
1119
    /* If count is NULL, assume full extent of var. */
1120
0
    if (!*count)
1121
0
    {
1122
0
        if (!(*count = malloc(varndims * sizeof(size_t))))
1123
0
            return NC_ENOMEM;
1124
0
        if ((stat = NC_getshape(ncid, varid, varndims, *count)))
1125
0
        {
1126
0
            free(*count);
1127
0
            *count = NULL;
1128
0
            return stat;
1129
0
        }
1130
0
    }
1131
1132
    /* If stride is NULL, do nothing, if *stride is NULL use all
1133
     * 1s. */
1134
0
    if (stride && !*stride)
1135
0
    {
1136
0
        int i;
1137
1138
0
        if (!(*stride = malloc(varndims * sizeof(ptrdiff_t))))
1139
0
            return NC_ENOMEM;
1140
0
        for (i = 0; i < varndims; i++)
1141
0
            (*stride)[i] = 1;
1142
0
    }
1143
1144
0
    return NC_NOERR;
1145
0
}
1146
1147
/**
1148
   @name Free String Resources
1149
1150
   Use this functions to free resources associated with ::NC_STRING
1151
   data.
1152
*/
1153
/*! @{ */
1154
/**
1155
   Free string space allocated by the library.
1156
1157
   When you read string type the library will allocate the storage
1158
   space for the data. This storage space must be freed, so pass the
1159
   pointer back to this function, when you're done with the data, and
1160
   it will free the string memory.
1161
1162
   @param len The number of character arrays in the array.
1163
   @param data The pointer to the data array.
1164
1165
   @return ::NC_NOERR No error.
1166
   @author Ed Hartnett
1167
*/
1168
int
1169
nc_free_string(size_t len, char **data)
1170
0
{
1171
0
    int i;
1172
0
    for (i = 0; i < len; i++)
1173
0
        free(data[i]);
1174
0
    return NC_NOERR;
1175
0
}
1176
/** @} */
1177
1178
/**
1179
   @name Variables Chunk Caches
1180
1181
   Use these functions to change the variable chunk cache settings.
1182
*/
1183
/*! @{ */
1184
/**
1185
   Change the cache settings for a chunked variable. This function allows
1186
   users to control the amount of memory used in the per-variable chunk
1187
   cache at the HDF5 level. Changing the chunk cache only has effect
1188
   until the file is closed. Once re-opened, the variable chunk cache
1189
   returns to its default value.
1190
1191
   Current cache settings for each var may be obtained with
1192
   nc_get_var_chunk_cache().
1193
1194
   Default values for these settings may be changed for the whole file
1195
   with nc_set_chunk_cache().
1196
1197
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
1198
   nc_create(), nc_def_grp(), or associated inquiry functions such as
1199
   nc_inq_ncid().
1200
   @param varid Variable ID
1201
   @param size The total size of the raw data chunk cache, in bytes.
1202
   @param nelems The number of chunk slots in the raw data chunk cache.
1203
   @param preemption The preemption, a value between 0 and 1 inclusive
1204
   that indicates how much chunks that have been fully read are favored
1205
   for preemption. A value of zero means fully read chunks are treated no
1206
   differently than other chunks (the preemption is strictly LRU) while a
1207
   value of one means fully read chunks are always preempted before other
1208
   chunks.
1209
1210
   @return ::NC_NOERR No error.
1211
   @return ::NC_EBADID Bad ncid.
1212
   @return ::NC_ENOTVAR Invalid variable ID.
1213
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
1214
   netcdf-4 file.
1215
   @return ::NC_EINVAL Invalid input
1216
1217
   @section nc_def_var_chunk_cache_example Example
1218
1219
   In this example from nc_test4/tst_coords.c, a variable is defined, and
1220
   the chunk cache settings are changed for that variable.
1221
1222
   @code
1223
   printf("**** testing setting cache values for coordinate variables...");
1224
   {
1225
   #define RANK_1 1
1226
   #define DIM0_NAME "d0"
1227
   #define CACHE_SIZE 1000000
1228
   #define CACHE_NELEMS 1009
1229
   #define CACHE_PREEMPTION .90
1230
1231
   int ncid, dimid, varid;
1232
   char name_in[NC_MAX_NAME + 1];
1233
1234
   if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
1235
   if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR;
1236
   if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR;
1237
   if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
1238
   if (nc_close(ncid)) ERR;
1239
1240
   ...
1241
   }
1242
   SUMMARIZE_ERR;
1243
   @endcode
1244
   @author Ed Hartnett
1245
*/
1246
int
1247
nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
1248
                       float preemption)
1249
64.5k
{
1250
64.5k
    NC* ncp;
1251
64.5k
    int stat = NC_check_id(ncid, &ncp);
1252
64.5k
    if(stat != NC_NOERR) return stat;
1253
64.5k
    return ncp->dispatch->set_var_chunk_cache(ncid, varid, size,
1254
64.5k
                                              nelems, preemption);
1255
64.5k
}
1256
1257
/**
1258
   Get the per-variable chunk cache settings from the HDF5
1259
   layer. These settings may be changed with nc_set_var_chunk_cache().
1260
1261
   See nc_set_chunk_cache() for a full discussion of these settings.
1262
1263
   @param ncid NetCDF or group ID, from a previous call to nc_open(),
1264
   nc_create(), nc_def_grp(), or associated inquiry functions such as
1265
   nc_inq_ncid().
1266
   @param varid Variable ID
1267
   @param sizep The total size of the raw data chunk cache, in bytes,
1268
   will be put here. @ref ignored_if_null.
1269
   @param nelemsp The number of chunk slots in the raw data chunk
1270
   cache hash table will be put here. @ref ignored_if_null.
1271
   @param preemptionp The preemption will be put here. The preemtion
1272
   value is between 0 and 1 inclusive and indicates how much chunks
1273
   that have been fully read are favored for preemption. A value of
1274
   zero means fully read chunks are treated no differently than other
1275
   chunks (the preemption is strictly LRU) while a value of one means
1276
   fully read chunks are always preempted before other chunks. @ref
1277
   ignored_if_null.
1278
1279
   @return ::NC_NOERR No error.
1280
   @return ::NC_EBADID Bad ncid.
1281
   @return ::NC_ENOTVAR Invalid variable ID.
1282
   @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3
1283
   netcdf-4 file.
1284
   @return ::NC_EINVAL Invalid input
1285
   @author Ed Hartnett
1286
*/
1287
int
1288
nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp,
1289
                       float *preemptionp)
1290
64.5k
{
1291
64.5k
    NC* ncp;
1292
64.5k
    int stat = NC_check_id(ncid, &ncp);
1293
64.5k
    if(stat != NC_NOERR) return stat;
1294
64.5k
    return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep,
1295
64.5k
                                              nelemsp, preemptionp);
1296
64.5k
}
1297
/** @} */
1298
/** @} */