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