Coverage Report

Created: 2026-08-31 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libsrc4/nc4dim.c
Line
Count
Source
1
/* Copyright 2003-2018, University Corporation for Atmospheric
2
 * Research. See the COPYRIGHT file for copying and redistribution
3
 * conditions. */
4
/**
5
 * @file
6
 * @internal This file is part of netcdf-4, a netCDF-like interface
7
 * for HDF5, or a HDF5 backend for netCDF, depending on your point of
8
 * view.
9
 *
10
 * This file handles the nc4 dimension functions.
11
 *
12
 * @author Ed Hartnett
13
 */
14
15
#include "nc4internal.h"
16
#include "nc4dispatch.h"
17
18
/**
19
 * @internal Netcdf-4 files might have more than one unlimited
20
 * dimension, but return the first one anyway.
21
 *
22
 * @note that this code is inconsistent with nc_inq
23
 *
24
 * @param ncid File and group ID.
25
 * @param unlimdimidp Pointer that gets ID of first unlimited
26
 * dimension, or -1.
27
 *
28
 * @return ::NC_NOERR No error.
29
 * @return ::NC_EBADID Bad ncid.
30
 * @author Ed Hartnett
31
 */
32
int
33
NC4_inq_unlimdim(int ncid, int *unlimdimidp)
34
0
{
35
0
    NC_GRP_INFO_T *grp, *g;
36
0
    NC_FILE_INFO_T *h5;
37
0
    NC_DIM_INFO_T *dim;
38
0
    int found = 0;
39
0
    int retval;
40
41
0
    LOG((2, "%s: called", __func__));
42
43
0
    if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
44
0
        return retval;
45
0
    assert(h5 && grp);
46
47
0
    if (unlimdimidp)
48
0
    {
49
        /* According to netcdf-3 manual, return -1 if there is no unlimited
50
           dimension. */
51
0
        *unlimdimidp = -1;
52
0
        for (g = grp; g && !found; g = g->parent)
53
0
        {
54
0
            for(size_t i=0;i<ncindexsize(grp->dim);i++)
55
0
            {
56
0
                dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
57
0
                if(dim == NULL) continue;
58
0
                if (dim->unlimited)
59
0
                {
60
0
                    *unlimdimidp = dim->hdr.id;
61
0
                    found++;
62
0
                    break;
63
0
                }
64
0
            }
65
0
        }
66
0
    }
67
68
0
    return NC_NOERR;
69
0
}
70
71
/**
72
 * @internal Given dim name, find its id.
73
 * Fully qualified names are legal
74
 * @param ncid File and group ID.
75
 * @param name Name of the dimension to find.
76
 * @param idp Pointer that gets dimension ID.
77
 *
78
 * @return ::NC_NOERR No error.
79
 * @return ::NC_EBADID Bad ncid.
80
 * @return ::NC_EBADDIM Dimension not found.
81
 * @return ::NC_EINVAL Invalid input. Name must be provided.
82
 * @author Ed Hartnett
83
 */
84
int
85
NC4_inq_dimid(int ncid, const char *name, int *idp)
86
0
{
87
0
    NC *nc = NULL;
88
0
    NC_GRP_INFO_T *grp = NULL;
89
0
    NC_GRP_INFO_T *g = NULL;
90
0
    NC_FILE_INFO_T *h5 = NULL;
91
0
    NC_DIM_INFO_T *dim = NULL;
92
0
    char norm_name[NC_MAX_NAME + 1];
93
0
    int retval = NC_NOERR;;
94
0
    int found = 0;
95
96
0
    LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
97
98
    /* Check input. */
99
0
    if (!name)
100
0
        {retval = NC_EINVAL; goto done;}
101
102
    /* If the first char is a /, this is a fully-qualified
103
     * name. Otherwise, this had better be a local name (i.e. no / in
104
     * the middle). */
105
0
    if (name[0] != '/' && strstr(name, "/"))
106
0
        {retval = NC_EINVAL; goto done;}
107
108
    /* Find metadata for this file. */
109
0
    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
110
0
        goto done;
111
0
    assert(h5 && nc && grp);
112
113
    /* Normalize name. */
114
0
    if ((retval = nc4_normalize_name(name, norm_name)))
115
0
        goto done;;
116
117
    /* If this is a fqn, then walk the sequence of parent groups to the last group
118
       and see if that group has a dimension of the right name */
119
0
    if(name[0] == '/') { /* FQN */
120
0
  int rootncid = (grp->nc4_info->root_grp->hdr.id | grp->nc4_info->controller->ext_ncid);
121
0
  int parent = 0;
122
0
  char* lastname = strrchr(norm_name,'/'); /* break off the last segment: the type name */
123
0
  if(lastname == norm_name)
124
0
      {retval = NC_EINVAL; goto done;}
125
0
  *lastname++ = '\0'; /* break off the lastsegment */
126
0
  if((retval = NC4_inq_grp_full_ncid(rootncid,norm_name,&parent))) 
127
0
      goto done;
128
  /* Get parent info */
129
0
  if((retval=nc4_find_nc4_grp(parent,&grp)))
130
0
      goto done;
131
  /* See if dim exists in this group */
132
0
        dim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,lastname);
133
0
  if(dim == NULL)   
134
0
      {retval = NC_EBADTYPE; goto done;}
135
0
  goto done;
136
0
    }
137
138
    /* check for a name match in this group and its parents */
139
0
    found = 0;
140
0
    for (g = grp; g ; g = g->parent) {
141
0
        dim = (NC_DIM_INFO_T*)ncindexlookup(g->dim,norm_name);
142
0
        if(dim != NULL) {found = 1; break;}
143
0
    }
144
0
    if(!found)
145
0
        {retval = NC_EBADDIM; goto done;}
146
147
0
done:
148
0
     if(retval == NC_NOERR) {
149
0
         assert(dim != NULL);
150
0
         if (idp)
151
0
            *idp = dim->hdr.id;
152
0
    }
153
0
    return retval;
154
0
}
155
156
/**
157
 * @internal Inquire about a dimension, returning its name and length
158
 * from the in-memory metadata model.
159
 *
160
 * This is the generic netcdf-4 implementation that works purely from
161
 * the in-memory NC_DIM_INFO_T structures. It returns dim->len
162
 * directly for all dimensions, including unlimited ones.
163
 *
164
 * The HDF5 layer provides its own HDF5_inq_dim() (in
165
 * libhdf5/hdf5dim.c) which overrides this for HDF5-backed files.
166
 * HDF5_inq_dim queries the actual HDF5 datasets via nc4_find_dim_len()
167
 * to determine the current extent of unlimited dimensions, since data
168
 * may have been written since the dimension was created. That function
169
 * requires HDF5-specific format_grp_info and cannot be used by UDF
170
 * handlers or other non-HDF5 dispatch layers.
171
 *
172
 * UDF handlers and other non-HDF5 dispatch layers should use this
173
 * function in their dispatch tables.
174
 *
175
 * @param ncid File and group ID.
176
 * @param dimid Dimension ID.
177
 * @param name Pointer that gets dimension name. Ignored if NULL.
178
 * @param lenp Pointer that gets dimension length. Ignored if NULL.
179
 *
180
 * @return ::NC_NOERR No error.
181
 * @return ::NC_EBADID Bad ncid.
182
 * @return ::NC_EBADDIM Dimension not found.
183
 * @author Edward Hartnett @date 5/7/2023
184
 */
185
int
186
NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
187
0
{
188
0
    NC_GRP_INFO_T *grp;
189
0
    NC_FILE_INFO_T *h5;
190
0
    NC_DIM_INFO_T *dim;
191
0
    int retval;
192
193
0
    LOG((2, "%s: ncid 0x%x dimid %d", __func__, ncid, dimid));
194
195
    /* Find our global metadata structure. */
196
0
    if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
197
0
        return retval;
198
0
    assert(h5 && grp);
199
200
    /* Find the dimension. */
201
0
    if ((retval = nc4_find_dim(grp, dimid, &dim, NULL)))
202
0
        return retval;
203
0
    assert(dim);
204
205
    /* Return the dimension name, if the caller wants it. */
206
0
    if (name && dim->hdr.name)
207
0
        strcpy(name, dim->hdr.name);
208
209
    /* Return the dimension length, if the caller wants it. */
210
0
    if (lenp)
211
0
        *lenp = dim->len;
212
213
0
    return NC_NOERR;
214
0
}
215
216
/**
217
 * @internal Returns an array of unlimited dimension ids.The user can
218
 * get the number of unlimited dimensions by first calling this with
219
 * NULL for the second pointer.
220
 *
221
 * @param ncid File and group ID.
222
 * @param nunlimdimsp Pointer that gets the number of unlimited
223
 * dimensions. Ignored if NULL.
224
 * @param unlimdimidsp Pointer that gets array of unlimited dimension
225
 * ID. Ignored if NULL.
226
 *
227
 * @return ::NC_NOERR No error.
228
 * @return ::NC_EBADID Bad ncid.
229
 * @author Ed Hartnett, Dennis Heimbigner
230
 */
231
int
232
NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
233
0
{
234
0
    NC_DIM_INFO_T *dim;
235
0
    NC_GRP_INFO_T *grp;
236
0
    NC *nc;
237
0
    NC_FILE_INFO_T *h5;
238
0
    int num_unlim = 0;
239
0
    int retval;
240
241
0
    LOG((2, "%s: ncid 0x%x", __func__, ncid));
242
243
    /* Find info for this file and group, and set pointer to each. */
244
0
    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
245
0
        return retval;
246
0
    assert(h5 && nc && grp);
247
248
    /* Get our dim info. */
249
0
    assert(h5);
250
0
    {
251
0
        for(size_t i=0;i<ncindexsize(grp->dim);i++)
252
0
        {
253
0
            dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
254
0
            if(dim == NULL) continue;
255
0
            if (dim->unlimited)
256
0
            {
257
0
                if (unlimdimidsp)
258
0
                    unlimdimidsp[num_unlim] = dim->hdr.id;
259
0
                num_unlim++;
260
0
            }
261
0
        }
262
0
    }
263
264
    /* Give the number if the user wants it. */
265
0
    if (nunlimdimsp)
266
0
        *nunlimdimsp = num_unlim;
267
268
0
    return NC_NOERR;
269
0
}