/src/netcdf-c/libdispatch/dgroup.c
Line | Count | Source |
1 | | /*! \file |
2 | | Functions for netCDF-4 features. |
3 | | |
4 | | Copyright 2018 University Corporation for Atmospheric |
5 | | Research/Unidata. See \ref copyright file for more info. */ |
6 | | |
7 | | #include "ncdispatch.h" |
8 | | |
9 | | /** \defgroup groups Groups |
10 | | |
11 | | NetCDF-4 added support for hierarchical groups within netCDF datasets. |
12 | | |
13 | | Groups are identified with a ncid, which identifies both the open |
14 | | file, and the group within that file. When a file is opened with |
15 | | nc_open or nc_create, the ncid for the root group of that file is |
16 | | provided. Using that as a starting point, users can add new groups, or |
17 | | list and navigate existing groups or rename a group. |
18 | | |
19 | | All netCDF calls take a ncid which determines where the call will take |
20 | | its action. For example, the nc_def_var function takes a ncid as its |
21 | | first parameter. It will create a variable in whichever group its ncid |
22 | | refers to. Use the root ncid provided by nc_create or nc_open to |
23 | | create a variable in the root group. Or use nc_def_grp to create a |
24 | | group and use its ncid to define a variable in the new group. |
25 | | |
26 | | Variable are only visible in the group in which they are defined. The |
27 | | same applies to attributes. “Global” attributes are associated with |
28 | | the group whose ncid is used. |
29 | | |
30 | | Dimensions are visible in their groups, and all child groups. |
31 | | |
32 | | Group operations are only permitted on netCDF-4 files - that is, files |
33 | | created with the HDF5 flag in nc_create(). Groups are not compatible |
34 | | with the netCDF classic data model, so files created with the |
35 | | ::NC_CLASSIC_MODEL file cannot contain groups (except the root group). |
36 | | |
37 | | Encoding both the open file id and group id in a single integer |
38 | | currently limits the number of groups per netCDF-4 file to no more |
39 | | than 32767. Similarly, the number of simultaneously open netCDF-4 |
40 | | files in one program context is limited to 32767. |
41 | | |
42 | | */ |
43 | | |
44 | | /** \{*/ /* All these functions are part of the above defgroup... */ |
45 | | |
46 | | /*! @ingroup groups |
47 | | Return the group ID for a group given the name. |
48 | | |
49 | | @param[in] ncid A valid file or group ncid. |
50 | | @param[in] name The name of the group you are querying. |
51 | | @param[out] grp_ncid Pointer to memory to hold the group ncid. |
52 | | |
53 | | @returns ::NC_NOERR No error. |
54 | | @returns ::NC_EBADID Bad ncid. |
55 | | @returns ::NC_ENOTNC4 Not a netCDF-4 file. |
56 | | @returns ::NC_ENOGRP Group not found. |
57 | | */ |
58 | | int nc_inq_ncid(int ncid, const char *name, int *grp_ncid) |
59 | 0 | { |
60 | 0 | NC* ncp; |
61 | 0 | int stat = NC_check_id(ncid,&ncp); |
62 | 0 | if(stat != NC_NOERR) return stat; |
63 | 0 | return ncp->dispatch->inq_ncid(ncid,name,grp_ncid); |
64 | 0 | } |
65 | | |
66 | | /*! @ingroup groups |
67 | | Get a list of groups or subgroups from a file or groupID. |
68 | | |
69 | | @param[in] ncid The ncid of the file or parent group. |
70 | | @param[out] numgrps Pointer to memory to hold the number of groups. |
71 | | @param[out] ncids Pointer to memory to hold the ncid for each group. |
72 | | |
73 | | @returns ::NC_NOERR No error. |
74 | | @returns ::NC_EBADID Bad ncid. |
75 | | */ |
76 | | int nc_inq_grps(int ncid, int *numgrps, int *ncids) |
77 | 0 | { |
78 | 0 | NC* ncp; |
79 | 0 | int stat = NC_check_id(ncid,&ncp); |
80 | 0 | if(stat != NC_NOERR) return stat; |
81 | 0 | return ncp->dispatch->inq_grps(ncid,numgrps,ncids); |
82 | 0 | } |
83 | | |
84 | | /*! @ingroup groups |
85 | | Get the name of a group given an ID. |
86 | | |
87 | | @param[in] ncid The ncid of the file or parent group. |
88 | | @param[out] name The name of the group associated with the id. |
89 | | |
90 | | @returns ::NC_NOERR No error. |
91 | | @returns ::NC_EBADID Bad ncid. |
92 | | */ |
93 | | int nc_inq_grpname(int ncid, char *name) |
94 | 0 | { |
95 | 0 | NC* ncp; |
96 | 0 | int stat = NC_check_id(ncid,&ncp); |
97 | 0 | if(stat != NC_NOERR) return stat; |
98 | 0 | return ncp->dispatch->inq_grpname(ncid,name); |
99 | 0 | } |
100 | | |
101 | | /*! @ingroup groups |
102 | | Get the full path/groupname of a group/subgroup given an ID. |
103 | | |
104 | | @param[in] ncid The ncid of the file or parent group. |
105 | | @param[out] lenp Pointer to memory to hold the length of the full name. |
106 | | @param[out] full_name Pointer to memory to hold the full name of the group including root/parent. |
107 | | |
108 | | @returns ::NC_NOERR No error. |
109 | | @returns ::NC_EBADID Bad ncid. |
110 | | @returns ::NC_ENOMEM Out of memory. |
111 | | */ |
112 | | |
113 | | int nc_inq_grpname_full(int ncid, size_t *lenp, char *full_name) |
114 | 0 | { |
115 | 0 | NC* ncp; |
116 | 0 | int stat = NC_check_id(ncid,&ncp); |
117 | 0 | if(stat != NC_NOERR) return stat; |
118 | 0 | return ncp->dispatch->inq_grpname_full(ncid,lenp,full_name); |
119 | 0 | } |
120 | | |
121 | | /*! @ingroup groups |
122 | | Get the length of a group name given an ID. |
123 | | |
124 | | @param[in] ncid The ncid of the group in question. |
125 | | @param[out] lenp Pointer to memory to hold the length of the name of the group in question. |
126 | | |
127 | | @returns ::NC_NOERR No error. |
128 | | @returns ::NC_EBADID Bad ncid. |
129 | | @returns ::NC_ENOMEM Out of memory. |
130 | | */ |
131 | | int nc_inq_grpname_len(int ncid, size_t *lenp) |
132 | 0 | { |
133 | 0 | int stat = nc_inq_grpname_full(ncid,lenp,NULL); |
134 | 0 | return stat; |
135 | 0 | } |
136 | | |
137 | | /*! @ingroup groups |
138 | | Get the ID of the parent based on a group ID. |
139 | | |
140 | | @param[in] ncid The ncid of the group in question. |
141 | | @param[out] parent_ncid Pointer to memory to hold the identifier of the parent of the group in question. |
142 | | |
143 | | @returns ::NC_NOERR No error. |
144 | | @returns ::NC_EBADID Bad ncid. |
145 | | @returns ::NC_ENOGRP No parent group (i.e. the root group was given). |
146 | | */ |
147 | | int nc_inq_grp_parent(int ncid, int *parent_ncid) |
148 | 0 | { |
149 | 0 | NC* ncp; |
150 | 0 | int stat = NC_check_id(ncid,&ncp); |
151 | 0 | if(stat != NC_NOERR) return stat; |
152 | 0 | return ncp->dispatch->inq_grp_parent(ncid,parent_ncid); |
153 | 0 | } |
154 | | |
155 | | /*! @ingroup groups |
156 | | Get a group ncid given the group name. |
157 | | |
158 | | @param[in] ncid The ncid of the file. |
159 | | @param[in] grp_name The name of the group in question. |
160 | | @param[out] grp_ncid Pointer to memory to hold the identifier of the group in question. |
161 | | |
162 | | @returns ::NC_NOERR No error. |
163 | | @returns ::NC_EBADID Bad ncid. |
164 | | @returns ::NC_ENOTNC4 Not a netCDF-4 file. |
165 | | @returns ::NC_ENOGRP Group not found. |
166 | | |
167 | | \note{This has same semantics as nc_inq_ncid} |
168 | | |
169 | | */ |
170 | | int nc_inq_grp_ncid(int ncid, const char *grp_name, int *grp_ncid) |
171 | 0 | { |
172 | 0 | return nc_inq_ncid(ncid,grp_name,grp_ncid); |
173 | 0 | } |
174 | | |
175 | | /*! @ingroup groups |
176 | | Get the full ncid given a group name. |
177 | | |
178 | | @param[in] ncid The ncid of the file. |
179 | | @param[in] full_name The full name of the group in question. |
180 | | @param[out] grp_ncid Pointer to memory to hold the identifier of the full group in question. |
181 | | |
182 | | @returns ::NC_NOERR No error. |
183 | | @returns ::NC_EBADID Bad ncid. |
184 | | @returns ::NC_ENOGRP Group not found. |
185 | | @returns ::NC_ENOMEM Out of memory. |
186 | | @returns ::NC_EINVAL Name is required. |
187 | | */ |
188 | | int nc_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid) |
189 | 0 | { |
190 | 0 | NC* ncp; |
191 | 0 | int stat = NC_check_id(ncid,&ncp); |
192 | 0 | if(stat != NC_NOERR) return stat; |
193 | 0 | return ncp->dispatch->inq_grp_full_ncid(ncid,full_name,grp_ncid); |
194 | 0 | } |
195 | | |
196 | | |
197 | | /*! @ingroup groups |
198 | | Get a list of varids associated with a group given a group ID. |
199 | | |
200 | | @param[in] ncid The ncid of the group in question. |
201 | | @param[out] nvars Pointer to memory to hold the number of variables in the group in question. |
202 | | @param[out] varids Pointer to memory to hold the variable ids contained by the group in question. |
203 | | |
204 | | @returns ::NC_NOERR No error. |
205 | | @returns ::NC_EBADID Bad ncid. |
206 | | */ |
207 | | int nc_inq_varids(int ncid, int *nvars, int *varids) |
208 | 0 | { |
209 | 0 | NC* ncp; |
210 | 0 | int stat = NC_check_id(ncid,&ncp); |
211 | 0 | if(stat != NC_NOERR) return stat; |
212 | 0 | return ncp->dispatch->inq_varids(ncid,nvars,varids); |
213 | 0 | } |
214 | | |
215 | | /*! @ingroup groups |
216 | | Retrieve a list of dimension ids associated with a group. |
217 | | |
218 | | @param[in] ncid The ncid of the group in question. |
219 | | @param[out] ndims Pointer to memory to contain the number of dimids associated with the group. |
220 | | @param[out] dimids Pointer to memory to contain the number of dimensions associated with the group. |
221 | | @param[in] include_parents If non-zero, parent groups are also traversed. |
222 | | |
223 | | @returns ::NC_NOERR No error. |
224 | | @returns ::NC_EBADID Bad ncid. |
225 | | */ |
226 | | int nc_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents) |
227 | 0 | { |
228 | 0 | NC* ncp; |
229 | 0 | int stat = NC_check_id(ncid,&ncp); |
230 | 0 | if(stat != NC_NOERR) return stat; |
231 | 0 | return ncp->dispatch->inq_dimids(ncid,ndims,dimids,include_parents); |
232 | 0 | } |
233 | | |
234 | | /*! @ingroup groups |
235 | | Retrieve a list of types associated with a group. |
236 | | |
237 | | @param[in] ncid The ncid for the group in question. |
238 | | @param[out] ntypes Pointer to memory to hold the number of typeids contained by the group in question. |
239 | | @param[out] typeids Pointer to memory to hold the typeids contained by the group in question. |
240 | | |
241 | | @returns ::NC_NOERR No error. |
242 | | @returns ::NC_EBADID Bad ncid. |
243 | | */ |
244 | | |
245 | | int nc_inq_typeids(int ncid, int *ntypes, int *typeids) |
246 | 0 | { |
247 | 0 | NC* ncp; |
248 | 0 | int stat = NC_check_id(ncid,&ncp); |
249 | 0 | if(stat != NC_NOERR) return stat; |
250 | 0 | return ncp->dispatch->inq_typeids(ncid,ntypes,typeids); |
251 | 0 | } |
252 | | |
253 | | /*! @ingroup groups |
254 | | Define a new group. |
255 | | |
256 | | The function nc_def_grp() adds a new |
257 | | group to an open netCDF dataset in define mode. It returns (as an |
258 | | argument) a group id, given the parent ncid and the name of the group. |
259 | | |
260 | | A group may be a top-level group if it is passed the ncid of the file, |
261 | | or a sub-group if passed the ncid of an existing group. |
262 | | |
263 | | @param[in] parent_ncid The ncid of the parent for the group. |
264 | | @param[in] name Name of the new group. |
265 | | @param[out] new_ncid Pointer to memory to hold the new ncid. |
266 | | |
267 | | @returns ::NC_NOERR No error. |
268 | | @returns ::NC_ENOTNC4 Not a netCDF-4 file. |
269 | | @returns ::NC_ENOTINDEFINE Not in define mode. |
270 | | @returns ::NC_ESTRICTNC3 Not permissible in nc4 classic mode. |
271 | | @returns ::NC_EPERM Write to read only. |
272 | | @returns ::NC_ENOMEM Memory allocation (malloc) failure. |
273 | | @returns ::NC_ENAMEINUSE String match to name in use. |
274 | | |
275 | | \section nc_def_grp_example Example |
276 | | |
277 | | Here is an example using nc_def_grp() to create a new group and |
278 | | define a variable in it. |
279 | | |
280 | | \code{.c} |
281 | | #include <netcdf.h> |
282 | | ... |
283 | | int ncid, grpid, varid, dimid; |
284 | | |
285 | | if (nc_create("foo.nc", NC_NETCDF4, &ncid)) ERR; |
286 | | |
287 | | if (nc_def_grp(ncid, "my_group", &grpid)) ERR; |
288 | | |
289 | | if (nc_def_dim(grpid, "x", 10, &dimid)) ERR; |
290 | | if (nc_def_var(grpid, "data", NC_INT, 1, &dimid, &varid)) ERR; |
291 | | |
292 | | if (nc_close(ncid)) ERR; |
293 | | \endcode |
294 | | |
295 | | */ |
296 | | int nc_def_grp(int parent_ncid, const char *name, int *new_ncid) |
297 | 0 | { |
298 | 0 | NC* ncp; |
299 | 0 | int stat = NC_check_id(parent_ncid,&ncp); |
300 | 0 | if(stat != NC_NOERR) return stat; |
301 | 0 | return ncp->dispatch->def_grp(parent_ncid,name,new_ncid); |
302 | 0 | } |
303 | | |
304 | | /*! @ingroup groups |
305 | | Rename a group. |
306 | | |
307 | | @param[in] grpid The ID for the group in question. |
308 | | @param[in] name The new name for the group. |
309 | | |
310 | | @returns ::NC_NOERR No error. |
311 | | @returns ::NC_EBADID Bad ncid. |
312 | | @returns ::NC_ENOTNC4 Not a netCDF-4 file. |
313 | | @returns ::NC_EPERM Write to read only. |
314 | | @returns ::NC_EBADNAME Bad name. |
315 | | @returns ::NC_ENAMEINUSE Name already in use. |
316 | | */ |
317 | | int nc_rename_grp(int grpid, const char *name) |
318 | 0 | { |
319 | 0 | NC* ncp; |
320 | 0 | int stat = NC_check_id(grpid,&ncp); |
321 | 0 | if(stat != NC_NOERR) return stat; |
322 | 0 | return ncp->dispatch->rename_grp(grpid,name); |
323 | 0 | } |
324 | | |
325 | | /*! @ingroup groups |
326 | | Print the metadata for a file. |
327 | | |
328 | | @param[in] ncid The ncid of an open file. |
329 | | |
330 | | @returns ::NC_NOERR No error. |
331 | | @returns ::NC_EBADID Bad ncid. |
332 | | */ |
333 | | int nc_show_metadata(int ncid) |
334 | 0 | { |
335 | 0 | NC* ncp; |
336 | 0 | int stat = NC_check_id(ncid,&ncp); |
337 | 0 | if(stat != NC_NOERR) return stat; |
338 | 0 | return ncp->dispatch->show_metadata(ncid); |
339 | 0 | } |
340 | | |
341 | | /** \} */ |