NetCDF  4.9.3
nc4grp.c
Go to the documentation of this file.
1 /* Copyright 2005-2018, University Corporation for Atmospheric
2  * Research. See COPYRIGHT file for copying and redistribution
3  * conditions. */
15 #include "nc4internal.h"
16 #include "nc4dispatch.h"
31 int
32 NC4_inq_ncid(int ncid, const char *name, int *grp_ncid)
33 {
34  NC_GRP_INFO_T *grp, *g;
35  NC_FILE_INFO_T *h5;
36  char norm_name[NC_MAX_NAME + 1];
37  int retval;
38 
39  LOG((2, "nc_inq_ncid: ncid 0x%x name %s", ncid, name));
40 
41  /* Find info for this file and group, and set pointer to each. */
42  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
43  return retval;
44  assert(h5);
45 
46  /* Short circuit the case of name == NULL => return the root group */
47  if(name == NULL) {
48  if(grp_ncid) {
49  NC_FILE_INFO_T* file = grp->nc4_info;
50  *grp_ncid = file->controller->ext_ncid | file->root_grp->hdr.id;
51  }
52  return NC_NOERR;
53  }
54 
55  /* Normalize name. */
56  if ((retval = nc4_check_name(name, norm_name)))
57  return retval;
58 
59  g = (NC_GRP_INFO_T*)ncindexlookup(grp->children,norm_name);
60  if(g != NULL)
61  {
62  if (grp_ncid)
63  *grp_ncid = grp->nc4_info->controller->ext_ncid | g->hdr.id;
64  return NC_NOERR;
65  }
66 
67  /* If we got here, we didn't find the named group. */
68  return NC_ENOGRP;
69 }
70 
83 int
84 NC4_inq_grps(int ncid, int *numgrps, int *ncids)
85 {
86  NC_GRP_INFO_T *grp, *g;
87  NC_FILE_INFO_T *h5;
88  int num = 0;
89  int retval;
90 
91  LOG((2, "nc_inq_grps: ncid 0x%x", ncid));
92 
93  /* Find info for this file and group, and set pointer to each. */
94  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
95  return retval;
96  assert(h5);
97 
98  /* Count the number of groups in this group. */
99  for(size_t i=0;i<ncindexsize(grp->children);i++)
100  {
101  g = (NC_GRP_INFO_T*)ncindexith(grp->children,i);
102  if(g == NULL) continue;
103  if (ncids)
104  {
105  /* Combine the nc_grpid in a bitwise or with the ext_ncid,
106  * which allows the returned ncid to carry both file and
107  * group information. */
108  *ncids = g->hdr.id | g->nc4_info->controller->ext_ncid;
109  ncids++;
110  }
111  num++;
112  }
113 
114  if (numgrps)
115  *numgrps = num;
116 
117  return NC_NOERR;
118 }
119 
131 int
132 NC4_inq_grpname(int ncid, char *name)
133 {
134  NC_GRP_INFO_T *grp;
135  NC_FILE_INFO_T *h5;
136  int retval;
137 
138  LOG((2, "nc_inq_grpname: ncid 0x%x", ncid));
139 
140  /* Find info for this file and group, and set pointer to each. */
141  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
142  return retval;
143  assert(h5);
144 
145  /* Copy the name. */
146  if (name)
147  strcpy(name, grp->hdr.name);
148 
149  return NC_NOERR;
150 }
151 
167 int
168 NC4_inq_grpname_full(int ncid, size_t *lenp, char *full_name)
169 {
170  char *name, grp_name[NC_MAX_NAME + 1];
171  int g, id = ncid, parent_id, *gid;
172  int i, ret = NC_NOERR;
173 
174  /* How many generations? */
175  for (g = 0; !NC4_inq_grp_parent(id, &parent_id); g++, id = parent_id)
176  ;
177 
178  /* Allocate storage. */
179  if (!(name = malloc((size_t)(g + 1) * (NC_MAX_NAME + 1) + 1)))
180  return NC_ENOMEM;
181  if (!(gid = malloc((size_t)(g + 1) * sizeof(int))))
182  {
183  free(name);
184  return NC_ENOMEM;
185  }
186  assert(name && gid);
187 
188  /* Always start with a "/" for the root group. */
189  strcpy(name, NC_GROUP_NAME);
190 
191  /* Get the ncids for all generations. */
192  gid[0] = ncid;
193  for (i = 1; i < g && !ret; i++)
194  ret = NC4_inq_grp_parent(gid[i - 1], &gid[i]);
195 
196  /* Assemble the full name. */
197  for (i = g - 1; !ret && i >= 0 && !ret; i--)
198  {
199  if ((ret = NC4_inq_grpname(gid[i], grp_name)))
200  break;
201  strcat(name, grp_name);
202  if (i)
203  strcat(name, "/");
204  }
205 
206  /* Give the user the length of the name, if he wants it. */
207  if (!ret && lenp)
208  *lenp = strlen(name);
209 
210  /* Give the user the name, if he wants it. */
211  if (!ret && full_name)
212  strcpy(full_name, name);
213 
214  free(gid);
215  free(name);
216 
217  return ret;
218 }
219 
234 int
235 NC4_inq_grp_parent(int ncid, int *parent_ncid)
236 {
237  NC_GRP_INFO_T *grp;
238  NC_FILE_INFO_T *h5;
239  int retval;
240 
241  LOG((2, "nc_inq_grp_parent: ncid 0x%x", ncid));
242 
243  /* Find info for this file and group. */
244  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
245  return retval;
246  assert(h5);
247 
248  /* Set the parent ncid, if there is one. */
249  if (grp->parent)
250  {
251  if (parent_ncid)
252  *parent_ncid = grp->nc4_info->controller->ext_ncid | grp->parent->hdr.id;
253  }
254  else
255  return NC_ENOGRP;
256 
257  return NC_NOERR;
258 }
259 
274 int
275 NC4_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid)
276 {
277  NC_GRP_INFO_T *grp;
278  NC_FILE_INFO_T *h5;
279  int id1 = ncid, id2;
280  char *cp, *full_name_cpy;
281  int ret;
282 
283  if (!full_name)
284  return NC_EINVAL;
285 
286  /* Find info for this file and group, and set pointer to each. */
287  if ((ret = nc4_find_grp_h5(ncid, &grp, &h5)))
288  return ret;
289  assert(h5);
290 
291  /* Copy full_name because strtok messes with the value it works
292  * with, and we don't want to mess up full_name. */
293  if (!(full_name_cpy = strdup(full_name)))
294  return NC_ENOMEM;
295 
296  /* Get the first part of the name. */
297  if (!(cp = strtok(full_name_cpy, "/")))
298  {
299  /* If "/" is passed, and this is the root group, return the root
300  * group id. */
301  if (!grp->parent)
302  id2 = ncid;
303  else
304  {
305  free(full_name_cpy);
306  return NC_ENOGRP;
307  }
308  }
309  else
310  {
311  /* Keep parsing the string. */
312  for (; cp; id1 = id2)
313  {
314  if ((ret = NC4_inq_ncid(id1, cp, &id2)))
315  {
316  free(full_name_cpy);
317  return ret;
318  }
319  cp = strtok(NULL, "/");
320  }
321  }
322 
323  /* Give the user the requested value. */
324  if (grp_ncid)
325  *grp_ncid = id2;
326 
327  free(full_name_cpy);
328 
329  return NC_NOERR;
330 }
331 
343 int
344 NC4_inq_varids(int ncid, int *nvars, int *varids)
345 {
346  NC_GRP_INFO_T *grp;
347  NC_FILE_INFO_T *h5;
348  NC_VAR_INFO_T *var;
349  int num_vars = 0;
350  int retval;
351 
352  LOG((2, "nc_inq_varids: ncid 0x%x", ncid));
353 
354  /* Find info for this file and group, and set pointer to each. */
355  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
356  return retval;
357  assert(h5);
358 
359  /* This is a netCDF-4 group. Round up them doggies and count
360  * 'em. The list is in correct (i.e. creation) order. */
361  for (size_t i=0; i < ncindexsize(grp->vars); i++)
362  {
363  var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
364  if (!var) continue;
365  if (varids)
366  varids[num_vars] = var->hdr.id;
367  num_vars++;
368  }
369 
370  /* If the user wants to know how many vars in the group, tell
371  * him. */
372  if (nvars)
373  *nvars = num_vars;
374 
375  return NC_NOERR;
376 }
377 
389 int int_cmp(const void *a, const void *b)
390 {
391  const int *ia = (const int *)a;
392  const int *ib = (const int *)b;
393  return *ia - *ib;
394 }
395 
411 int
412 NC4_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents)
413 {
414  NC_GRP_INFO_T *grp, *g;
415  NC_FILE_INFO_T *h5;
416  NC_DIM_INFO_T *dim;
417  int num = 0;
418  int retval;
419 
420  LOG((2, "nc_inq_dimids: ncid 0x%x include_parents: %d", ncid,
421  include_parents));
422 
423  /* Find info for this file and group, and set pointer to each. */
424  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
425  return retval;
426  assert(h5);
427 
428  /* First count them. */
429  num = ncindexcount(grp->dim);
430  if (include_parents) {
431  for (g = grp->parent; g; g = g->parent)
432  num += ncindexcount(g->dim);
433  }
434 
435  /* If the user wants the dimension ids, get them. */
436  if (dimids)
437  {
438  int n = 0;
439 
440  /* Get dimension ids from this group. */
441  for(size_t i=0;i<ncindexsize(grp->dim);i++) {
442  dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
443  if(dim == NULL) continue;
444  dimids[n++] = dim->hdr.id;
445  }
446 
447  /* Get dimension ids from parent groups. */
448  if (include_parents)
449  for (g = grp->parent; g; g = g->parent) {
450  for(size_t i=0;i<ncindexsize(g->dim);i++) {
451  dim = (NC_DIM_INFO_T*)ncindexith(g->dim,i);
452  if(dim == NULL) continue;
453  dimids[n++] = dim->hdr.id;
454  }
455  }
456  qsort(dimids, (size_t)num, sizeof(int), int_cmp);
457  }
458 
459  /* If the user wants the number of dims, give it. */
460  if (ndims)
461  *ndims = num;
462 
463  return NC_NOERR;
464 }
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:458
#define NC_ENOGRP
No group found.
Definition: netcdf.h:515
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:388
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:291
#define NC_NOERR
No Error.
Definition: netcdf.h:378