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
NC4_inq_unlimdim(int ncid,int * unlimdimidp)33 NC4_inq_unlimdim(int ncid, int *unlimdimidp)
34 {
35    NC *nc;
36    NC_GRP_INFO_T *grp, *g;
37    NC_FILE_INFO_T *h5;
38    NC_DIM_INFO_T *dim;
39    int found = 0;
40    int retval;
41    int i;
42 
43    LOG((2, "%s: called", __func__));
44 
45    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
46       return retval;
47    assert(h5 && nc && grp);
48 
49    if (unlimdimidp)
50    {
51       /* According to netcdf-3 manual, return -1 if there is no unlimited
52          dimension. */
53       *unlimdimidp = -1;
54       for (g = grp; g && !found; g = g->parent)
55       {
56          for(i=0;i<ncindexsize(grp->dim);i++)
57          {
58             dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
59             if(dim == NULL) continue;
60             if (dim->unlimited)
61             {
62                *unlimdimidp = dim->hdr.id;
63                found++;
64                break;
65             }
66          }
67       }
68    }
69 
70    return NC_NOERR;
71 }
72 
73 /**
74  * @internal Given dim name, find its id.
75  *
76  * @param ncid File and group ID.
77  * @param name Name of the dimension to find.
78  * @param idp Pointer that gets dimension ID.
79  *
80  * @return ::NC_NOERR No error.
81  * @return ::NC_EBADID Bad ncid.
82  * @return ::NC_EBADDIM Dimension not found.
83  * @return ::NC_EINVAL Invalid input. Name must be provided.
84  * @author Ed Hartnett
85  */
86 int
NC4_inq_dimid(int ncid,const char * name,int * idp)87 NC4_inq_dimid(int ncid, const char *name, int *idp)
88 {
89    NC *nc;
90    NC_GRP_INFO_T *grp, *g;
91    NC_FILE_INFO_T *h5;
92    NC_DIM_INFO_T *dim;
93    char norm_name[NC_MAX_NAME + 1];
94    int retval;
95    int found;
96 
97    LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
98 
99    /* Check input. */
100    if (!name)
101       return NC_EINVAL;
102 
103    /* Find metadata for this file. */
104    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
105       return retval;
106    assert(h5 && nc && grp);
107 
108    /* Normalize name. */
109    if ((retval = nc4_normalize_name(name, norm_name)))
110       return retval;
111 
112    /* check for a name match in this group and its parents */
113    found = 0;
114    for (g = grp; g ; g = g->parent) {
115       dim = (NC_DIM_INFO_T*)ncindexlookup(g->dim,norm_name);
116       if(dim != NULL) {found = 1; break;}
117    }
118    if(!found)
119       return NC_EBADDIM;
120    assert(dim != NULL);
121    if (idp)
122       *idp = dim->hdr.id;
123    return NC_NOERR;
124 }
125 
126 /**
127  * @internal Returns an array of unlimited dimension ids.The user can
128  * get the number of unlimited dimensions by first calling this with
129  * NULL for the second pointer.
130  *
131  * @param ncid File and group ID.
132  * @param nunlimdimsp Pointer that gets the number of unlimited
133  * dimensions. Ignored if NULL.
134  * @param unlimdimidsp Pointer that gets arrray of unlimited dimension
135  * ID. Ignored if NULL.
136  *
137  * @return ::NC_NOERR No error.
138  * @return ::NC_EBADID Bad ncid.
139  * @author Ed Hartnett, Dennis Heimbigner
140  */
141 int
NC4_inq_unlimdims(int ncid,int * nunlimdimsp,int * unlimdimidsp)142 NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
143 {
144    NC_DIM_INFO_T *dim;
145    NC_GRP_INFO_T *grp;
146    NC *nc;
147    NC_FILE_INFO_T *h5;
148    int num_unlim = 0;
149    int retval;
150    int i;
151 
152    LOG((2, "%s: ncid 0x%x", __func__, ncid));
153 
154    /* Find info for this file and group, and set pointer to each. */
155    if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
156       return retval;
157    assert(h5 && nc && grp);
158 
159    /* Get our dim info. */
160    assert(h5);
161    {
162       for(i=0;i<ncindexsize(grp->dim);i++)
163       {
164          dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
165          if(dim == NULL) continue;
166          if (dim->unlimited)
167          {
168             if (unlimdimidsp)
169                unlimdimidsp[num_unlim] = dim->hdr.id;
170             num_unlim++;
171          }
172       }
173    }
174 
175    /* Give the number if the user wants it. */
176    if (nunlimdimsp)
177       *nunlimdimsp = num_unlim;
178 
179    return NC_NOERR;
180 }
181