Coverage Report

Created: 2025-11-15 08:43

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