NetCDF  4.6.1
nc4dim.c
Go to the documentation of this file.
1 /* Copyright 2003-2018, University Corporation for Atmospheric
2  * Research. See the COPYRIGHT file for copying and redistribution
3  * conditions. */
15 #include "nc4internal.h"
16 #include "nc4dispatch.h"
17 
32 int
33 NC4_inq_unlimdim(int ncid, int *unlimdimidp)
34 {
35  NC *nc;
36  NC_GRP_INFO_T *grp, *g;
37  NC_HDF5_FILE_INFO_T *h5;
38  NC_DIM_INFO_T *dim;
39  int found = 0;
40  int retval;
41 
42  LOG((2, "%s: called", __func__));
43 
44  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
45  return retval;
46  assert(h5 && nc && grp);
47 
48  if (unlimdimidp)
49  {
50  /* According to netcdf-3 manual, return -1 if there is no unlimited
51  dimension. */
52  *unlimdimidp = -1;
53  for (g = grp; g && !found; g = g->parent)
54  {
55  for (dim = g->dim; dim; dim = dim->l.next)
56  {
57  if (dim->unlimited)
58  {
59  *unlimdimidp = dim->dimid;
60  found++;
61  break;
62  }
63  }
64  }
65  }
66 
67  return NC_NOERR;
68 }
69 
93 int
94 NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
95 {
96  NC *nc;
97  NC_GRP_INFO_T *grp;
98  NC_HDF5_FILE_INFO_T *h5;
99  NC_DIM_INFO_T *dim;
100  char norm_name[NC_MAX_NAME + 1];
101  int retval = NC_NOERR;
102  uint32_t nn_hash;
103 
104  LOG((2, "%s: ncid 0x%x name %s len %d", __func__, ncid, name,
105  (int)len));
106 
107  /* Find our global metadata structure. */
108  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
109  return retval;
110  assert(h5 && nc && grp);
111 
112  /* If the file is read-only, return an error. */
113  if (h5->no_write)
114  return NC_EPERM;
115 
116  /* Check some stuff if strict nc3 rules are in effect. */
117  if (h5->cmode & NC_CLASSIC_MODEL)
118  {
119  /* Only one limited dimenson for strict nc3. */
120  if (len == NC_UNLIMITED)
121  for (dim = grp->dim; dim; dim = dim->l.next)
122  if (dim->unlimited)
123  return NC_EUNLIMIT;
124 
125  /* Must be in define mode for stict nc3. */
126  if (!(h5->flags & NC_INDEF))
127  return NC_ENOTINDEFINE;
128  }
129 
130  /* Make sure this is a valid netcdf name. */
131  if ((retval = nc4_check_name(name, norm_name)))
132  return retval;
133 
134  /* For classic model: dim length has to fit in a 32-bit unsigned
135  * int, as permitted for 64-bit offset format. */
136  if (h5->cmode & NC_CLASSIC_MODEL)
137  if(len > X_UINT_MAX) /* Backward compat */
138  return NC_EDIMSIZE;
139 
140  /* Create a hash of the name. */
141  nn_hash = hash_fast(norm_name, strlen(norm_name));
142 
143  /* Make sure the name is not already in use. */
144  for (dim = grp->dim; dim; dim = dim->l.next)
145  if (nn_hash == dim->hash && !strncmp(dim->name, norm_name, NC_MAX_NAME))
146  return NC_ENAMEINUSE;
147 
148  /* If it's not in define mode, enter define mode. Do this only
149  * after checking all input data, so we only enter define mode if
150  * input is good. */
151  if (!(h5->flags & NC_INDEF))
152  if ((retval = NC4_redef(ncid)))
153  return retval;
154 
155  /* Add a dimension to the list. The ID must come from the file
156  * information, since dimids are visible in more than one group. */
157  if ((retval = nc4_dim_list_add(&grp->dim, &dim)))
158  return retval;
159  dim->dimid = grp->nc4_info->next_dimid++;
160 
161  /* Initialize the metadata for this dimension. */
162  if (!(dim->name = strdup(norm_name)))
163  return NC_ENOMEM;
164  dim->len = len;
165  if (len == NC_UNLIMITED)
166  dim->unlimited = NC_TRUE;
167 
168  dim->hash = nn_hash;
169 
170  /* Pass back the dimid. */
171  if (idp)
172  *idp = dim->dimid;
173 
174  return retval;
175 }
176 
190 int
191 NC4_inq_dimid(int ncid, const char *name, int *idp)
192 {
193  NC *nc;
194  NC_GRP_INFO_T *grp, *g;
195  NC_HDF5_FILE_INFO_T *h5;
196  NC_DIM_INFO_T *dim;
197  char norm_name[NC_MAX_NAME + 1];
198  int finished = 0;
199  int retval;
200  uint32_t shash;
201 
202  LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
203 
204  /* Check input. */
205  if (!name)
206  return NC_EINVAL;
207 
208  /* Find metadata for this file. */
209  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
210  return retval;
211  assert(h5 && nc && grp);
212 
213  /* Normalize name. */
214  if ((retval = nc4_normalize_name(name, norm_name)))
215  return retval;
216 
217  shash = hash_fast(norm_name, strlen(norm_name));
218 
219  /* Go through each dim and check for a name match. */
220  for (g = grp; g && !finished; g = g->parent)
221  for (dim = g->dim; dim; dim = dim->l.next)
222  if (dim->hash == shash && !strncmp(dim->name, norm_name, NC_MAX_NAME))
223  {
224  if (idp)
225  *idp = dim->dimid;
226  return NC_NOERR;
227  }
228 
229  return NC_EBADDIM;
230 }
231 
248 int
249 NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
250 {
251  NC *nc;
252  NC_HDF5_FILE_INFO_T *h5;
253  NC_GRP_INFO_T *grp, *dim_grp;
254  NC_DIM_INFO_T *dim;
255  int ret = NC_NOERR;
256 
257  LOG((2, "%s: ncid 0x%x dimid %d", __func__, ncid, dimid));
258 
259  /* Find our global metadata structure. */
260  if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
261  return ret;
262  assert(h5 && nc && grp);
263 
264  /* Find the dimension and its home group. */
265  if ((ret = nc4_find_dim(grp, dimid, &dim, &dim_grp)))
266  return ret;
267  assert(dim);
268 
269  /* Return the dimension name, if the caller wants it. */
270  if (name && dim->name)
271  strcpy(name, dim->name);
272 
273  /* Return the dimension length, if the caller wants it. */
274  if (lenp)
275  {
276  if (dim->unlimited)
277  {
278  /* Since this is an unlimited dimension, go to the file
279  and see how many records there are. Take the max number
280  of records from all the vars that share this
281  dimension. */
282  *lenp = 0;
283  if ((ret = nc4_find_dim_len(dim_grp, dimid, &lenp)))
284  return ret;
285  }
286  else
287  {
288  if (dim->too_long)
289  {
290  ret = NC_EDIMSIZE;
291  *lenp = NC_MAX_UINT;
292  }
293  else
294  *lenp = dim->len;
295  }
296  }
297 
298  return ret;
299 }
300 
320 int
321 NC4_rename_dim(int ncid, int dimid, const char *name)
322 {
323  NC *nc;
324  NC_GRP_INFO_T *grp;
325  NC_HDF5_FILE_INFO_T *h5;
326  NC_DIM_INFO_T *dim, *tmp_dim;
327  char norm_name[NC_MAX_NAME + 1];
328  int retval;
329 
330  if (!name)
331  return NC_EINVAL;
332 
333  LOG((2, "%s: ncid 0x%x dimid %d name %s", __func__, ncid,
334  dimid, name));
335 
336  /* Find info for this file and group, and set pointer to each. */
337  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
338  return retval;
339  assert(nc && h5 && grp);
340 
341  /* Trying to write to a read-only file? No way, Jose! */
342  if (h5->no_write)
343  return NC_EPERM;
344 
345  /* Make sure this is a valid netcdf name. */
346  if ((retval = nc4_check_name(name, norm_name)))
347  return retval;
348 
349  /* Check if name is in use, and retain a pointer to the correct dim */
350  tmp_dim = NULL;
351  for (dim = grp->dim; dim; dim = dim->l.next)
352  {
353  if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
354  return NC_ENAMEINUSE;
355  if (dim->dimid == dimid)
356  tmp_dim = dim;
357  }
358  if (!tmp_dim)
359  return NC_EBADDIM;
360  dim = tmp_dim;
361 
362  /* Check for renaming dimension w/o variable */
363  if (dim->hdf_dimscaleid)
364  {
365  /* Sanity check */
366  assert(!dim->coord_var);
367  LOG((3, "dim %s is a dim without variable", dim->name));
368 
369  /* Delete the dimscale-only dataset. */
370  if ((retval = delete_existing_dimscale_dataset(grp, dimid, dim)))
371  return retval;
372  }
373 
374  /* Give the dimension its new name in metadata. UTF8 normalization
375  * has been done. */
376  assert(dim->name);
377  free(dim->name);
378  if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
379  return NC_ENOMEM;
380  strcpy(dim->name, norm_name);
381  dim->hash = hash_fast(norm_name, strlen(norm_name));
382  LOG((3, "dim is now named %s", dim->name));
383 
384  /* Check if dimension was a coordinate variable, but names are
385  * different now */
386  if (dim->coord_var && strcmp(dim->name, dim->coord_var->name))
387  {
388  /* Break up the coordinate variable */
389  if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim)))
390  return retval;
391  }
392 
393  /* Check if dimension should become a coordinate variable. */
394  if (!dim->coord_var)
395  {
396  NC_VAR_INFO_T *var;
397 
398  /* Attempt to find a variable with the same name as the
399  * dimension in the current group. */
400  if ((retval = nc4_find_var(grp, dim->name, &var)))
401  return retval;
402 
403  /* Check if we found a variable and the variable has the
404  * dimension in index 0. */
405  if (var && var->dim[0] == dim)
406  {
407  /* Sanity check */
408  assert(var->dimids[0] == dim->dimid);
409 
410  /* Reform the coordinate variable. */
411  if ((retval = nc4_reform_coord_var(grp, var, dim)))
412  return retval;
413  }
414  }
415 
416  return NC_NOERR;
417 }
418 
434 int
435 NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
436 {
437  NC_DIM_INFO_T *dim;
438  NC_GRP_INFO_T *grp;
439  NC *nc;
440  NC_HDF5_FILE_INFO_T *h5;
441  int num_unlim = 0;
442  int retval;
443 
444  LOG((2, "%s: ncid 0x%x", __func__, ncid));
445 
446  /* Find info for this file and group, and set pointer to each. */
447  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
448  return retval;
449  assert(h5 && nc && grp);
450 
451  /* Get our dim info. */
452  assert(h5);
453  {
454  for (dim=grp->dim; dim; dim=dim->l.next)
455  {
456  if (dim->unlimited)
457  {
458  if (unlimdimidsp)
459  unlimdimidsp[num_unlim] = dim->dimid;
460  num_unlim++;
461  }
462  }
463  }
464 
465  /* Give the number if the user wants it. */
466  if (nunlimdimsp)
467  *nunlimdimsp = num_unlim;
468 
469  return NC_NOERR;
470 }
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:395
#define NC_EUNLIMIT
NC_UNLIMITED size already in use.
Definition: netcdf.h:374
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:135
#define NC_ENOTINDEFINE
Operation not allowed in data mode.
Definition: netcdf.h:331
#define NC_EBADDIM
Invalid dimension id or name.
Definition: netcdf.h:358
#define NC_EDIMSIZE
Invalid dimension size.
Definition: netcdf.h:397
#define NC_ENAMEINUSE
String match to name in use.
Definition: netcdf.h:354
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:325
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:265
#define NC_UNLIMITED
Size argument to nc_def_dim() for an unlimited dimension.
Definition: netcdf.h:235
#define NC_MAX_UINT
Max or min values for a type.
Definition: netcdf.h:101
#define NC_EPERM
Write to read only.
Definition: netcdf.h:326
#define NC_NOERR
No Error.
Definition: netcdf.h:315

Return to the Main Unidata NetCDF page.
Generated on Wed Aug 1 2018 05:36:48 for NetCDF. NetCDF is a Unidata library.