/src/netcdf-c/libsrc4/nc4dim.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | int i; |
41 | |
|
42 | 0 | LOG((2, "%s: called", __func__)); |
43 | |
|
44 | 0 | if ((retval = nc4_find_grp_h5(ncid, &grp, &h5))) |
45 | 0 | return retval; |
46 | 0 | assert(h5 && grp); |
47 | | |
48 | 0 | if (unlimdimidp) |
49 | 0 | { |
50 | | /* According to netcdf-3 manual, return -1 if there is no unlimited |
51 | | dimension. */ |
52 | 0 | *unlimdimidp = -1; |
53 | 0 | for (g = grp; g && !found; g = g->parent) |
54 | 0 | { |
55 | 0 | for(i=0;i<ncindexsize(grp->dim);i++) |
56 | 0 | { |
57 | 0 | dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i); |
58 | 0 | if(dim == NULL) continue; |
59 | 0 | if (dim->unlimited) |
60 | 0 | { |
61 | 0 | *unlimdimidp = dim->hdr.id; |
62 | 0 | found++; |
63 | 0 | break; |
64 | 0 | } |
65 | 0 | } |
66 | 0 | } |
67 | 0 | } |
68 | |
|
69 | 0 | return NC_NOERR; |
70 | 0 | } |
71 | | |
72 | | /** |
73 | | * @internal Given dim name, find its id. |
74 | | * Fully qualified names are legal |
75 | | * @param ncid File and group ID. |
76 | | * @param name Name of the dimension to find. |
77 | | * @param idp Pointer that gets dimension ID. |
78 | | * |
79 | | * @return ::NC_NOERR No error. |
80 | | * @return ::NC_EBADID Bad ncid. |
81 | | * @return ::NC_EBADDIM Dimension not found. |
82 | | * @return ::NC_EINVAL Invalid input. Name must be provided. |
83 | | * @author Ed Hartnett |
84 | | */ |
85 | | int |
86 | | NC4_inq_dimid(int ncid, const char *name, int *idp) |
87 | 0 | { |
88 | 0 | NC *nc = NULL; |
89 | 0 | NC_GRP_INFO_T *grp = NULL; |
90 | 0 | NC_GRP_INFO_T *g = NULL; |
91 | 0 | NC_FILE_INFO_T *h5 = NULL; |
92 | 0 | NC_DIM_INFO_T *dim = NULL; |
93 | 0 | char norm_name[NC_MAX_NAME + 1]; |
94 | 0 | int retval = NC_NOERR;; |
95 | 0 | int found = 0; |
96 | |
|
97 | 0 | LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name)); |
98 | | |
99 | | /* Check input. */ |
100 | 0 | if (!name) |
101 | 0 | {retval = NC_EINVAL; goto done;} |
102 | | |
103 | | /* If the first char is a /, this is a fully-qualified |
104 | | * name. Otherwise, this had better be a local name (i.e. no / in |
105 | | * the middle). */ |
106 | 0 | if (name[0] != '/' && strstr(name, "/")) |
107 | 0 | {retval = NC_EINVAL; goto done;} |
108 | | |
109 | | /* Find metadata for this file. */ |
110 | 0 | if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) |
111 | 0 | goto done; |
112 | 0 | assert(h5 && nc && grp); |
113 | | |
114 | | /* Normalize name. */ |
115 | 0 | if ((retval = nc4_normalize_name(name, norm_name))) |
116 | 0 | goto done;; |
117 | | |
118 | | /* If this is a fqn, then walk the sequence of parent groups to the last group |
119 | | and see if that group has a dimension of the right name */ |
120 | 0 | if(name[0] == '/') { /* FQN */ |
121 | 0 | int rootncid = (grp->nc4_info->root_grp->hdr.id | grp->nc4_info->controller->ext_ncid); |
122 | 0 | int parent = 0; |
123 | 0 | char* lastname = strrchr(norm_name,'/'); /* break off the last segment: the type name */ |
124 | 0 | if(lastname == norm_name) |
125 | 0 | {retval = NC_EINVAL; goto done;} |
126 | 0 | *lastname++ = '\0'; /* break off the lastsegment */ |
127 | 0 | if((retval = NC4_inq_grp_full_ncid(rootncid,norm_name,&parent))) |
128 | 0 | goto done; |
129 | | /* Get parent info */ |
130 | 0 | if((retval=nc4_find_nc4_grp(parent,&grp))) |
131 | 0 | goto done; |
132 | | /* See if dim exists in this group */ |
133 | 0 | dim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,lastname); |
134 | 0 | if(dim == NULL) |
135 | 0 | {retval = NC_EBADTYPE; goto done;} |
136 | 0 | goto done; |
137 | 0 | } |
138 | | |
139 | | /* check for a name match in this group and its parents */ |
140 | 0 | found = 0; |
141 | 0 | for (g = grp; g ; g = g->parent) { |
142 | 0 | dim = (NC_DIM_INFO_T*)ncindexlookup(g->dim,norm_name); |
143 | 0 | if(dim != NULL) {found = 1; break;} |
144 | 0 | } |
145 | 0 | if(!found) |
146 | 0 | {retval = NC_EBADDIM; goto done;} |
147 | | |
148 | 0 | done: |
149 | 0 | if(retval == NC_NOERR) { |
150 | 0 | assert(dim != NULL); |
151 | 0 | if (idp) |
152 | 0 | *idp = dim->hdr.id; |
153 | 0 | } |
154 | 0 | return retval; |
155 | 0 | } |
156 | | |
157 | | /** |
158 | | * @internal Returns an array of unlimited dimension ids.The user can |
159 | | * get the number of unlimited dimensions by first calling this with |
160 | | * NULL for the second pointer. |
161 | | * |
162 | | * @param ncid File and group ID. |
163 | | * @param nunlimdimsp Pointer that gets the number of unlimited |
164 | | * dimensions. Ignored if NULL. |
165 | | * @param unlimdimidsp Pointer that gets arrray of unlimited dimension |
166 | | * ID. Ignored if NULL. |
167 | | * |
168 | | * @return ::NC_NOERR No error. |
169 | | * @return ::NC_EBADID Bad ncid. |
170 | | * @author Ed Hartnett, Dennis Heimbigner |
171 | | */ |
172 | | int |
173 | | NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) |
174 | 0 | { |
175 | 0 | NC_DIM_INFO_T *dim; |
176 | 0 | NC_GRP_INFO_T *grp; |
177 | 0 | NC *nc; |
178 | 0 | NC_FILE_INFO_T *h5; |
179 | 0 | int num_unlim = 0; |
180 | 0 | int retval; |
181 | 0 | int i; |
182 | |
|
183 | 0 | LOG((2, "%s: ncid 0x%x", __func__, ncid)); |
184 | | |
185 | | /* Find info for this file and group, and set pointer to each. */ |
186 | 0 | if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) |
187 | 0 | return retval; |
188 | 0 | assert(h5 && nc && grp); |
189 | | |
190 | | /* Get our dim info. */ |
191 | 0 | assert(h5); |
192 | 0 | { |
193 | 0 | for(i=0;i<ncindexsize(grp->dim);i++) |
194 | 0 | { |
195 | 0 | dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i); |
196 | 0 | if(dim == NULL) continue; |
197 | 0 | if (dim->unlimited) |
198 | 0 | { |
199 | 0 | if (unlimdimidsp) |
200 | 0 | unlimdimidsp[num_unlim] = dim->hdr.id; |
201 | 0 | num_unlim++; |
202 | 0 | } |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | | /* Give the number if the user wants it. */ |
207 | 0 | if (nunlimdimsp) |
208 | 0 | *nunlimdimsp = num_unlim; |
209 | |
|
210 | 0 | return NC_NOERR; |
211 | 0 | } |