Coverage Report

Created: 2023-05-28 06:42

/src/netcdf-c/libdispatch/dattinq.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2018 University Corporation for Atmospheric
2
Research/Unidata. See \ref copyright file for more info.  */
3
/**
4
 * @file
5
 * Attribute inquiry functions
6
 *
7
 * These functions find out about attributes.
8
 */
9
#include "ncdispatch.h"
10
11
/**
12
 * @name Learning about Attributes
13
 *
14
 * Functions to learn about the attributes in a file. */
15
/** \{ */ /* All these functions are part of this named group... */
16
17
/**
18
 * @ingroup attributes
19
 * Return information about a netCDF attribute.
20
 *
21
 * The function nc_inq_att returns the attribute's type and length.
22
 *
23
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
24
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
25
 * nc_inq_ncid().
26
 *
27
 * @param varid Variable ID of the attribute's variable, or
28
 * ::NC_GLOBAL for a global attribute.
29
 *
30
 * @param name Pointer to the location for the returned attribute \ref
31
 * object_name. \ref ignored_if_null.
32
 *
33
 * @param xtypep Pointer to location for returned attribute [data
34
 * type](https://docs.unidata.ucar.edu/nug/current/md_types.html#data_type). \ref
35
 * ignored_if_null.
36
 *
37
 * @param lenp Pointer to location for returned number of values
38
 * currently stored in the attribute. For attributes of type
39
 * ::NC_CHAR, you should not assume that this includes a trailing zero
40
 * byte; it doesn't if the attribute was stored without a trailing
41
 * zero byte, for example from a FORTRAN program. Before using the
42
 * value as a C string, make sure it is null-terminated. \ref
43
 * ignored_if_null.
44
 *
45
 * @section nc_inq_att_example Example
46
 *
47
 * Here is an example using nc_inq_att() to find out the type and
48
 * length of a variable attribute named valid_range for a netCDF
49
 * variable named rh and a global attribute named title in an existing
50
 * netCDF dataset named foo.nc:
51
 *
52
@code
53
     #include <netcdf.h>
54
        ...
55
     int  status;
56
     int  ncid;
57
     int  rh_id;
58
     nc_type vr_type, t_type;
59
     size_t  vr_len, t_len;
60
61
        ...
62
     status = nc_open("foo.nc", NC_NOWRITE, &ncid);
63
     if (status != NC_NOERR) handle_error(status);
64
        ...
65
     status = nc_inq_varid (ncid, "rh", &rh_id);
66
     if (status != NC_NOERR) handle_error(status);
67
        ...
68
     status = nc_inq_att (ncid, rh_id, "valid_range", &vr_type, &vr_len);
69
     if (status != NC_NOERR) handle_error(status);
70
     status = nc_inq_att (ncid, NC_GLOBAL, "title", &t_type, &t_len);
71
     if (status != NC_NOERR) handle_error(status);
72
@endcode
73
 *
74
 * @return ::NC_NOERR no error.
75
 * @return ::NC_EBADID bad ncid.
76
 * @return ::NC_ENOTVAR bad varid.
77
 * @return ::NC_EBADGRPID bad group ID.
78
 * @return ::NC_EBADNAME bad name.
79
 * @return ::NC_ENOTATT attribute not found.
80
 * @return ::NC_ECHAR illegal conversion to or from NC_CHAR.
81
 * @return ::NC_ENOMEM out of memory.
82
 * @return ::NC_ERANGE range error when converting data.
83
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
84
*/
85
int
86
nc_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
87
     size_t *lenp)
88
0
{
89
0
   NC* ncp;
90
0
   int stat = NC_check_id(ncid, &ncp);
91
0
   if(stat != NC_NOERR) return stat;
92
0
   return ncp->dispatch->inq_att(ncid, varid, name, xtypep, lenp);
93
0
}
94
95
/**
96
 * @ingroup attributes
97
 * Find an attribute ID.
98
 *
99
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
100
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
101
 * nc_inq_ncid().
102
 *
103
 * @param varid Variable ID of the attribute's variable, or
104
 * ::NC_GLOBAL for a global attribute.
105
 *
106
 * @param name Attribute \ref object_name.
107
 *
108
 * @param idp Pointer to location for returned attribute number that
109
 * specifies which attribute this is for this variable (or which
110
 * global attribute). If you already know the attribute name, knowing
111
 * its number is not very useful, because accessing information about
112
 * an attribute requires its name.
113
 *
114
 * @section nc_inq_attid_example Example
115
 *
116
 * Here is an example using nc_inq_attid() from
117
 * nc_test4/tst_vars2.c. In this example three attributes are created
118
 * in a file. Then it is re-opened, and their IDs are checked. They
119
 * will be 0, 1, and 2, in the order that the attributes were written
120
 * to the file.
121
 *
122
@code
123
     #include <netcdf.h>
124
     ...
125
     printf("**** testing fill value with three other attributes...");
126
     {
127
#define NUM_LEADERS 3
128
         char leader[NUM_LEADERS][NC_MAX_NAME + 1] = {"hair_length_of_strategoi",
129
                                                      "hair_length_of_Miltiades",
130
                                                      "hair_length_of_Darius_I"};
131
         short hair_length[NUM_LEADERS] = {3, 11, 4};
132
         short short_in;
133
         int a;
134
135
         if (nc_create(FILE_NAME, cmode, &ncid)) ERR;
136
         if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
137
         if (nc_def_var(ncid, VAR_NAME, NC_BYTE, NUM_DIMS, dimids, &varid)) ERR;
138
         for (a = 0; a < NUM_LEADERS; a++)
139
            if (nc_put_att_short(ncid, varid, leader[a], NC_SHORT, 1, &hair_length[a])) ERR;
140
         if (nc_put_att_schar(ncid, varid, _FillValue, NC_BYTE, 1, &fill_value)) ERR;
141
         if (nc_close(ncid)) ERR;
142
143
         if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
144
         for (a = 0; a < NUM_LEADERS; a++)
145
         {
146
            ...
147
            if (nc_inq_attid(ncid, 0, leader[a], &attnum_in)) ERR;
148
            if (attnum_in != a) ERR;
149
         }
150
151
         if (nc_close(ncid)) ERR;
152
@endcode
153
 *
154
 * @return ::NC_NOERR no error.
155
 * @return ::NC_EBADID bad ncid.
156
 * @return ::NC_ENOTVAR bad varid.
157
 * @return ::NC_EBADGRPID bad group ID.
158
 * @return ::NC_EBADNAME bad name.
159
 * @return ::NC_ENOTATT attribute not found.
160
 * @return ::NC_ENOMEM out of memory.
161
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
162
*/
163
int
164
nc_inq_attid(int ncid, int varid, const char *name, int *idp)
165
0
{
166
0
   NC* ncp;
167
0
   int stat = NC_check_id(ncid, &ncp);
168
0
   if(stat != NC_NOERR) return stat;
169
0
   return ncp->dispatch->inq_attid(ncid, varid, name, idp);
170
0
}
171
172
/**
173
 * @ingroup attributes
174
 * Find the name of an attribute.
175
 *
176
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
177
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
178
 * nc_inq_ncid().
179
 *
180
 * @param varid Variable ID of the attribute's variable, or
181
 * ::NC_GLOBAL for a global attribute.
182
 *
183
 * @param attnum Attribute number. The attributes for each variable
184
 * are numbered from 0 (the first attribute) to natts-1, where natts
185
 * is the number of attributes for the variable, as returned from a
186
 * call to nc_inq_varnatts().
187
 *
188
 * @param name Pointer to the location for the returned attribute \ref
189
 * object_name.
190
 *
191
 * @section nc_inq_attname_example Example
192
 *
193
 * Here is an example from nc_test4/tst_atts3.c a variable of every
194
 * type is added to a file, with names from the 'names' array. Then
195
 * the file is re-opened, and the names of the attributes are checked
196
 * in a for loop.
197
 *
198
@code
199
     #include <netcdf.h>
200
     ...
201
#define NUM_ATTS 8
202
#define ATT_MAX_NAME 25
203
int
204
tst_att_ordering(int cmode)
205
{
206
   int ncid;
207
   char name[NUM_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf",
208
              "Gd", "Gatt-name-dashes", "Gatt.name.dots"};
209
   int len[NUM_ATTS] = {0, 2, 3, 3, 3, 3, 1, 1};
210
   signed char b[2] = {-128, 127};
211
   short s[3] = {-32768, 0, 32767};
212
   int i[3] = {42, 0, -42};
213
   float f[3] = {42.0, -42.0, 42.0};
214
   double d[3] = {420.0, -420.0, 420.0};
215
   int att_name_dashes = -1, att_name_dots = -2;
216
   char name_in[NC_MAX_NAME];
217
   int j;
218
219
   if (nc_create(FILE_NAME, cmode, &ncid)) ERR;
220
   ...
221
   if (nc_put_att_text(ncid, NC_GLOBAL, name[0], len[0], NULL)) ERR;
222
   if (nc_put_att_schar(ncid, NC_GLOBAL, name[1], NC_BYTE, len[1], b)) ERR;
223
   if (nc_put_att_short(ncid, NC_GLOBAL, name[2], NC_SHORT, len[2], s)) ERR;
224
   if (nc_put_att_int(ncid, NC_GLOBAL, name[3], NC_INT, len[3], i)) ERR;
225
   if (nc_put_att_float(ncid, NC_GLOBAL, name[4], NC_FLOAT, len[4], f)) ERR;
226
   if (nc_put_att_double(ncid, NC_GLOBAL, name[5], NC_DOUBLE, len[5], d)) ERR;
227
   if (nc_put_att_int(ncid, NC_GLOBAL, name[6], NC_INT, len[6], &att_name_dashes)) ERR;
228
   if (nc_put_att_int(ncid, NC_GLOBAL, name[7], NC_INT, len[7], &att_name_dots)) ERR;
229
   if (nc_close(ncid)) ERR;
230
231
   ...
232
   if (nc_open(FILE_NAME, 0, &ncid)) ERR;
233
   for (j = 0; j < NUM_ATTS; j++)
234
   {
235
      if (nc_inq_attname(ncid, NC_GLOBAL, j, name_in)) ERR;
236
      if (strcmp(name_in, name[j])) ERR;
237
   }
238
239
   if (nc_close(ncid)) ERR;
240
241
@endcode
242
 *
243
 * @return ::NC_NOERR no error.
244
 * @return ::NC_EBADID bad ncid.
245
 * @return ::NC_ENOTVAR bad varid.
246
 * @return ::NC_EBADGRPID bad group ID.
247
 * @return ::NC_EBADNAME bad name.
248
 * @return ::NC_ENOTATT attribute not found.
249
 * @return ::NC_ECHAR illegal conversion to or from NC_CHAR.
250
 * @return ::NC_ENOMEM out of memory.
251
 * @return ::NC_ERANGE range error when converting data.
252
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
253
*/
254
int
255
nc_inq_attname(int ncid, int varid, int attnum, char *name)
256
0
{
257
0
   NC* ncp;
258
0
   int stat = NC_check_id(ncid, &ncp);
259
0
   if(stat != NC_NOERR) return stat;
260
0
   return ncp->dispatch->inq_attname(ncid, varid, attnum, name);
261
0
}
262
263
/**
264
 * @ingroup attributes
265
 * Find number of global or group attributes.
266
 *
267
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
268
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
269
 * nc_inq_ncid().
270
 *
271
 * @param nattsp Pointer where number of global or group attributes
272
 * will be written. \ref ignored_if_null.
273
 *
274
 * @section nc_inq_natts_example Example
275
 *
276
 * Here is an example from nc_test4/tst_vars.c:
277
 *
278
@code
279
     #include <netcdf.h>
280
     ...
281
int
282
check_4D_example(char *file_name, int expected_format)
283
{
284
   int ncid;
285
   int format, ndims_in, nvars_in, natts_in;
286
   ...
287
288
   if (nc_open(file_name, 0, &ncid)) ERR;
289
   ...
290
   if (nc_inq_natts(ncid, &natts_in)) ERR;
291
   if (natts_in != 0) ERR;
292
@endcode
293
294
 * @return ::NC_NOERR no error.
295
 * @return ::NC_EBADID bad ncid.
296
 * @return ::NC_EBADGRPID bad group ID.
297
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
298
*/
299
int
300
nc_inq_natts(int ncid, int *nattsp)
301
0
{
302
0
   NC* ncp;
303
0
   int stat = NC_check_id(ncid, &ncp);
304
0
   if(stat != NC_NOERR) return stat;
305
0
   if(nattsp == NULL) return NC_NOERR;
306
0
   return ncp->dispatch->inq(ncid, NULL, NULL, nattsp, NULL);
307
0
}
308
309
/**
310
 * @ingroup attributes
311
 * Find the type of an attribute.
312
 *
313
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
314
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
315
 * nc_inq_ncid().
316
 *
317
 * @param varid Variable ID of the attribute's variable, or
318
 * ::NC_GLOBAL for a global or group attribute.
319
 *
320
 * @param name Attribute \ref object_name.
321
 *
322
 * @param xtypep Pointer to location for returned attribute [data
323
 * type](https://docs.unidata.ucar.edu/nug/current/md_types.html#data_type).
324
 *
325
 * @section nc_inq_atttype_example Example
326
 *
327
 * Here is an example from nc_test4/tst_h_refs.c. In this example, a
328
 * file with an integer attribute is open. It's type is confirmed to
329
 * be NC_INT.
330
 *
331
@code
332
     #include <netcdf.h>
333
     ...
334
    printf("*** Checking accessing file through netCDF-4 API...");
335
    {
336
  int ncid, varid, attid;
337
  nc_type type;
338
339
  if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
340
        ...
341
  if (nc_inq_atttype(ncid, NC_GLOBAL, INT_ATT_NAME, &type)) ERR;
342
  if (type != NC_INT) ERR;
343
344
@endcode
345
 *
346
 * @return ::NC_NOERR no error.
347
 * @return ::NC_EBADID bad ncid.
348
 * @return ::NC_ENOTVAR bad varid.
349
 * @return ::NC_EBADGRPID bad group ID.
350
 * @return ::NC_EBADNAME bad name.
351
 * @return ::NC_ENOTATT attribute not found.
352
 * @return ::NC_ECHAR illegal conversion to or from NC_CHAR.
353
 * @return ::NC_ENOMEM out of memory.
354
 * @return ::NC_ERANGE range error when converting data.
355
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
356
*/
357
int
358
nc_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep)
359
0
{
360
0
   NC* ncp;
361
0
   int stat = NC_check_id(ncid, &ncp);
362
0
   if(stat != NC_NOERR) return stat;
363
0
   return ncp->dispatch->inq_att(ncid, varid, name, xtypep, NULL);
364
0
}
365
366
/**
367
 * @ingroup attributes
368
 * Find the length of an attribute.
369
 *
370
 * @param ncid NetCDF or group ID, from a previous call to nc_open(),
371
 * nc_create(), nc_def_grp(), or associated inquiry functions such as
372
 * nc_inq_ncid().
373
 *
374
 * @param varid Variable ID of the attribute's variable, or
375
 * ::NC_GLOBAL for a global or group attribute.
376
 *
377
 * @param name Attribute \ref object_name.
378
 *
379
 * @param lenp Pointer to location for returned number of values
380
 * currently stored in the attribute. Before using the value as a C
381
 * string, make sure it is null-terminated. \ref ignored_if_null.
382
 *
383
 * @section nc_inq_attlen_example Example
384
 *
385
 * Here is an example from nc_test4/tst_h_scalar.c which checks the
386
 * attributes of an already-open netCDF file. In this code, the length
387
 * of two attributes are checked, and found to be 1.
388
 *
389
@code
390
     #include <netcdf.h>
391
     ...
392
int
393
check_attrs(int ncid, int obj)
394
{
395
    int attid;
396
    int natts = 0;
397
    size_t len;
398
    nc_type type;
399
    char *vlstr;
400
    char fixstr[10];
401
    int x;
402
403
    ...
404
    if (nc_inq_attlen(ncid, obj, VSTR_ATT1_NAME, &len)) ERR_GOTO;
405
    if (len != 1) ERR_GOTO;
406
    ...
407
    if (nc_inq_attlen(ncid, obj, VSTR_ATT2_NAME, &len)) ERR_GOTO;
408
    if (len != 1) ERR_GOTO;
409
410
@endcode
411
412
 * @return ::NC_NOERR no error.
413
 * @return ::NC_EBADID bad ncid.
414
 * @return ::NC_ENOTVAR bad varid.
415
 * @return ::NC_EBADGRPID bad group ID.
416
 * @return ::NC_EBADNAME bad name.
417
 * @return ::NC_ENOTATT attribute not found.
418
 * @return ::NC_ECHAR illegal conversion to or from NC_CHAR.
419
 * @return ::NC_ENOMEM out of memory.
420
 * @return ::NC_ERANGE range error when converting data.
421
 * @author Glenn Davis, Ed Hartnett, Dennis Heimbigner
422
*/
423
int
424
nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp)
425
0
{
426
0
   NC* ncp;
427
0
   int stat = NC_check_id(ncid, &ncp);
428
0
   if(stat != NC_NOERR) return stat;
429
0
   return ncp->dispatch->inq_att(ncid, varid, name, NULL, lenp);
430
0
}
431
432
/*! \} */  /* End of named group ...*/