NetCDF  4.6.0
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);
47 
48  /* According to netcdf-3 manual, return -1 if there is no unlimited
49  dimension. */
50  *unlimdimidp = -1;
51  for (g = grp; g && !found; g = g->parent)
52  {
53  for (dim = g->dim; dim; dim = dim->l.next)
54  {
55  if (dim->unlimited)
56  {
57  *unlimdimidp = dim->dimid;
58  found++;
59  break;
60  }
61  }
62  }
63 
64  return NC_NOERR;
65 }
66 
89 int
90 NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
91 {
92  NC *nc;
93  NC_GRP_INFO_T *grp;
94  NC_HDF5_FILE_INFO_T *h5;
95  NC_DIM_INFO_T *dim;
96  char norm_name[NC_MAX_NAME + 1];
97  int retval = NC_NOERR;
98  uint32_t nn_hash;
99 
100  LOG((2, "%s: ncid 0x%x name %s len %d", __func__, ncid, name,
101  (int)len));
102 
103  /* Find our global metadata structure. */
104  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
105  return retval;
106  assert(h5 && nc && grp);
107 
108  /* If the file is read-only, return an error. */
109  if (h5->no_write)
110  return NC_EPERM;
111 
112  /* Check some stuff if strict nc3 rules are in effect. */
113  if (h5->cmode & NC_CLASSIC_MODEL)
114  {
115  /* Only one limited dimenson for strict nc3. */
116  if (len == NC_UNLIMITED)
117  for (dim = grp->dim; dim; dim = dim->l.next)
118  if (dim->unlimited)
119  return NC_EUNLIMIT;
120 
121  /* Must be in define mode for stict nc3. */
122  if (!(h5->flags & NC_INDEF))
123  return NC_ENOTINDEFINE;
124  }
125 
126  /* If it's not in define mode, enter define mode. */
127  if (!(h5->flags & NC_INDEF))
128  if ((retval = NC4_redef(ncid)))
129  return retval;
130 
131  /* Make sure this is a valid netcdf name. */
132  if ((retval = nc4_check_name(name, norm_name)))
133  return retval;
134 
135  /* For classic model: dim length has to fit in a 32-bit unsigned
136  * int, as permitted for 64-bit offset format. */
137  if (h5->cmode & NC_CLASSIC_MODEL)
138  if(len > X_UINT_MAX) /* Backward compat */
139  return NC_EDIMSIZE;
140 
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  /* Add a dimension to the list. The ID must come from the file
149  * information, since dimids are visible in more than one group. */
150  nc4_dim_list_add(&grp->dim, &dim);
151  dim->dimid = grp->nc4_info->next_dimid++;
152 
153  /* Initialize the metadata for this dimension. */
154  if (!(dim->name = strdup(norm_name)))
155  return NC_ENOMEM;
156  dim->len = len;
157  if (len == NC_UNLIMITED)
158  dim->unlimited = NC_TRUE;
159 
160  dim->hash = nn_hash;
161 
162  /* Pass back the dimid. */
163  if (idp)
164  *idp = dim->dimid;
165 
166  return retval;
167 }
168 
181 int
182 NC4_inq_dimid(int ncid, const char *name, int *idp)
183 {
184  NC *nc;
185  NC_GRP_INFO_T *grp, *g;
186  NC_HDF5_FILE_INFO_T *h5;
187  NC_DIM_INFO_T *dim;
188  char norm_name[NC_MAX_NAME + 1];
189  int finished = 0;
190  int retval;
191  uint32_t shash;
192 
193  LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
194 
195  /* Find metadata for this file. */
196  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
197  return retval;
198 
199  assert(h5);
200  assert(nc && grp);
201 
202  /* Normalize name. */
203  if ((retval = nc4_normalize_name(name, norm_name)))
204  return retval;
205 
206  shash = hash_fast(norm_name, strlen(norm_name));
207 
208  /* Go through each dim and check for a name match. */
209  for (g = grp; g && !finished; g = g->parent)
210  for (dim = g->dim; dim; dim = dim->l.next)
211  if (dim->hash == shash && !strncmp(dim->name, norm_name, NC_MAX_NAME))
212  {
213  if (idp)
214  *idp = dim->dimid;
215  return NC_NOERR;
216  }
217 
218  return NC_EBADDIM;
219 }
220 
236 int
237 NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
238 {
239  NC *nc;
240  NC_HDF5_FILE_INFO_T *h5;
241  NC_GRP_INFO_T *grp, *dim_grp;
242  NC_DIM_INFO_T *dim;
243  int ret = NC_NOERR;
244 
245  LOG((2, "%s: ncid 0x%x dimid %d", __func__, ncid, dimid));
246 
247  /* Find our global metadata structure. */
248  if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
249  return ret;
250 
251  assert(h5);
252  assert(nc && grp);
253 
254  /* Find the dimension and its home group. */
255  if ((ret = nc4_find_dim(grp, dimid, &dim, &dim_grp)))
256  return ret;
257  assert(dim);
258 
259  /* Return the dimension name, if the caller wants it. */
260  if (name && dim->name)
261  strcpy(name, dim->name);
262 
263  /* Return the dimension length, if the caller wants it. */
264  if (lenp)
265  {
266  if (dim->unlimited)
267  {
268  /* Since this is an unlimited dimension, go to the file
269  and see how many records there are. Take the max number
270  of records from all the vars that share this
271  dimension. */
272  *lenp = 0;
273  if ((ret = nc4_find_dim_len(dim_grp, dimid, &lenp)))
274  return ret;
275  }
276  else
277  {
278  if (dim->too_long)
279  {
280  ret = NC_EDIMSIZE;
281  *lenp = NC_MAX_UINT;
282  }
283  else
284  *lenp = dim->len;
285  }
286  }
287 
288  return ret;
289 }
290 
310 int
311 NC4_rename_dim(int ncid, int dimid, const char *name)
312 {
313  NC *nc;
314  NC_GRP_INFO_T *grp;
315  NC_HDF5_FILE_INFO_T *h5;
316  NC_DIM_INFO_T *dim, *tmp_dim;
317  char norm_name[NC_MAX_NAME + 1];
318  int retval;
319 
320  if (!name)
321  return NC_EINVAL;
322 
323  LOG((2, "%s: ncid 0x%x dimid %d name %s", __func__, ncid,
324  dimid, name));
325 
326  /* Find info for this file and group, and set pointer to each. */
327  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
328  return retval;
329  assert(nc && h5 && grp);
330 
331  /* Trying to write to a read-only file? No way, Jose! */
332  if (h5->no_write)
333  return NC_EPERM;
334 
335  /* Make sure this is a valid netcdf name. */
336  if ((retval = nc4_check_name(name, norm_name)))
337  return retval;
338 
339  /* Check if name is in use, and retain a pointer to the correct dim */
340  tmp_dim = NULL;
341  for (dim = grp->dim; dim; dim = dim->l.next)
342  {
343  if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
344  return NC_ENAMEINUSE;
345  if (dim->dimid == dimid)
346  tmp_dim = dim;
347  }
348  if (!tmp_dim)
349  return NC_EBADDIM;
350  dim = tmp_dim;
351 
352  /* Check for renaming dimension w/o variable. */
353  if (dim->hdf_dimscaleid)
354  {
355  /* Sanity check */
356  assert(!dim->coord_var);
357  LOG((3, "dim %s is a dim without variable", dim->name));
358 
359  /* Delete the dimscale-only dataset. */
360  if ((retval = delete_existing_dimscale_dataset(grp, dimid, dim)))
361  return retval;
362  }
363 
364  /* Give the dimension its new name in metadata. UTF8 normalization
365  * has been done. */
366  assert(dim->name);
367  free(dim->name);
368  if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
369  return NC_ENOMEM;
370  strcpy(dim->name, norm_name);
371  dim->hash = hash_fast(norm_name, strlen(norm_name));
372  LOG((3, "dim is now named %s", dim->name));
373 
374  /* Check if dimension was a coordinate variable, but names are
375  * different now */
376  if (dim->coord_var && strcmp(dim->name, dim->coord_var->name))
377  {
378  /* Break up the coordinate variable */
379  if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim)))
380  return retval;
381  }
382 
383  /* Check if dimension should become a coordinate variable. */
384  if (!dim->coord_var)
385  {
386  NC_VAR_INFO_T *var;
387 
388  /* Attempt to find a variable with the same name as the
389  * dimension in the current group. */
390  if ((retval = nc4_find_var(grp, dim->name, &var)))
391  return retval;
392 
393  /* Check if we found a variable and the variable has the
394  * dimension in index 0. */
395  if (var && var->dim[0] == dim)
396  {
397  /* Sanity check */
398  assert(var->dimids[0] == dim->dimid);
399 
400  /* Reform the coordinate variable. */
401  if ((retval = nc4_reform_coord_var(grp, var, dim)))
402  return retval;
403  }
404  }
405 
406  return NC_NOERR;
407 }
408 
424 int
425 NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
426 {
427  NC_DIM_INFO_T *dim;
428  NC_GRP_INFO_T *grp;
429  NC *nc;
430  NC_HDF5_FILE_INFO_T *h5;
431  int num_unlim = 0;
432  int retval;
433 
434  LOG((2, "%s: ncid 0x%x", __func__, ncid));
435 
436  /* Find info for this file and group, and set pointer to each. */
437  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
438  return retval;
439 
440  /* Get our dim info. */
441  assert(h5);
442  {
443  for (dim=grp->dim; dim; dim=dim->l.next)
444  {
445  if (dim->unlimited)
446  {
447  if (unlimdimidsp)
448  unlimdimidsp[num_unlim] = dim->dimid;
449  num_unlim++;
450  }
451  }
452  }
453 
454  /* Give the number if the user wants it. */
455  if (nunlimdimsp)
456  *nunlimdimsp = num_unlim;
457 
458  return NC_NOERR;
459 }
460 
461 
#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 Fri Feb 9 2018 19:21:24 for NetCDF. NetCDF is a Unidata library.