NetCDF  4.9.2
nc4attr.c
Go to the documentation of this file.
1 /* Copyright 2003-2018, University Corporation for Atmospheric
2  * Research. See COPYRIGHT file for copying and redistribution
3  * conditions. */
19 #include "nc.h"
20 #include "nc4internal.h"
21 #include "nc4dispatch.h"
22 #include "ncdispatch.h"
23 
45 int
46 nc4_get_att_ptrs(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var,
47  const char *name, nc_type *xtype, nc_type mem_type,
48  size_t *lenp, int *attnum, void *data)
49 {
50  NC_ATT_INFO_T *att = NULL;
51  int my_attnum = -1;
52  int need_to_convert = 0;
53  int range_error = NC_NOERR;
54  void *bufr = NULL;
55  size_t type_size;
56  int varid;
57  int retval;
58 
59  LOG((3, "%s: mem_type %d", __func__, mem_type));
60 
61  /* Get the varid, or NC_GLOBAL. */
62  varid = var ? var->hdr.id : NC_GLOBAL;
63 
64  if (attnum)
65  my_attnum = *attnum;
66 
67  if (name == NULL)
68  BAIL(NC_EBADNAME);
69 
70  /* Find the attribute, if it exists. */
71  if ((retval = nc4_find_grp_att(grp, varid, name, my_attnum, &att)))
72  return retval;
73 
74  /* If mem_type is NC_NAT, it means we want to use the attribute's
75  * file type as the mem type as well. */
76  if (mem_type == NC_NAT)
77  mem_type = att->nc_typeid;
78 
79  /* If the attribute is NC_CHAR, and the mem_type isn't, or vice
80  * versa, that's a freakish attempt to convert text to
81  * numbers. Some pervert out there is trying to pull a fast one!
82  * Send him an NC_ECHAR error. */
83  if (data && att->len)
84  if ((att->nc_typeid == NC_CHAR && mem_type != NC_CHAR) ||
85  (att->nc_typeid != NC_CHAR && mem_type == NC_CHAR))
86  BAIL(NC_ECHAR); /* take that, you freak! */
87 
88  /* Copy the info. */
89  if (lenp)
90  *lenp = att->len;
91  if (xtype)
92  *xtype = att->nc_typeid;
93  if (attnum) {
94  *attnum = att->hdr.id;
95  }
96 
97  /* Zero len attributes are easy to read! */
98  if (!att->len)
99  BAIL(NC_NOERR);
100 
101  /* Later on, we will need to know the size of this type. */
102  if ((retval = nc4_get_typelen_mem(h5, mem_type, &type_size)))
103  BAIL(retval);
104 
105  /* We may have to convert data. Treat NC_CHAR the same as
106  * NC_UBYTE. If the mem_type is NAT, don't try any conversion - use
107  * the attribute's type. */
108  if (data && att->len && mem_type != att->nc_typeid &&
109  mem_type != NC_NAT &&
110  !(mem_type == NC_CHAR &&
111  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE)))
112  {
113  if (!(bufr = malloc((size_t)(att->len * type_size))))
114  BAIL(NC_ENOMEM);
115  need_to_convert++;
116  if ((retval = nc4_convert_type(att->data, bufr, att->nc_typeid,
117  mem_type, (size_t)att->len, &range_error,
118  NULL, (h5->cmode & NC_CLASSIC_MODEL),
119  NC_NOQUANTIZE, 0)))
120  BAIL(retval);
121 
122  /* For strict netcdf-3 rules, ignore erange errors between UBYTE
123  * and BYTE types. */
124  if ((h5->cmode & NC_CLASSIC_MODEL) &&
125  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE) &&
126  (mem_type == NC_UBYTE || mem_type == NC_BYTE) &&
127  range_error)
128  range_error = 0;
129  }
130  else
131  {
132  bufr = att->data;
133  }
134 
135  /* If the caller wants data, copy it for him. If he hasn't
136  allocated enough memory for it, he will burn in segmentation
137  fault hell, writhing with the agony of undiscovered memory
138  bugs! */
139  if (data)
140  {
141 #ifdef SEPDATA
142  if (att->vldata)
143  {
144  size_t base_typelen;
145  nc_hvl_t *vldest = data;
146  NC_TYPE_INFO_T *type;
147  int i;
148 
149  /* Get the type object for the attribute's type */
150  if ((retval = nc4_find_type(h5, att->nc_typeid, &type)))
151  BAIL(retval);
152 
153  /* Retrieve the size of the base type */
154  if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, &base_typelen)))
155  BAIL(retval);
156 
157  for (i = 0; i < att->len; i++)
158  {
159  vldest[i].len = att->vldata[i].len;
160  if (!(vldest[i].p = malloc(vldest[i].len * base_typelen)))
161  BAIL(NC_ENOMEM);
162  memcpy(vldest[i].p, att->vldata[i].p, vldest[i].len * base_typelen);
163  }
164  }
165  else if (att->stdata)
166  {
167  int i;
168  for (i = 0; i < att->len; i++)
169  {
170  /* Check for NULL pointer for string (valid in HDF5) */
171  if(att->stdata[i])
172  {
173  if (!(((char **)data)[i] = strdup(att->stdata[i])))
174  BAIL(NC_ENOMEM);
175  }
176  else
177  ((char **)data)[i] = att->stdata[i];
178  }
179  }
180  else
181  {
182  memcpy(data, bufr, (size_t)(att->len * type_size));
183  }
184 #else
185  {
186  if((retval = nc_copy_data(h5->controller->ext_ncid,mem_type,bufr,att->len,data)))
187  BAIL(retval);
188  }
189 #endif
190  }
191 
192 exit:
193  if (need_to_convert)
194  free(bufr);
195  if (range_error)
196  retval = NC_ERANGE;
197  return retval;
198 }
199 
221 int
222 nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
223  nc_type mem_type, size_t *lenp, int *attnum, void *data)
224 {
225  NC_FILE_INFO_T *h5;
226  NC_GRP_INFO_T *grp;
227  NC_VAR_INFO_T *var = NULL;
228  char norm_name[NC_MAX_NAME + 1];
229  int retval;
230 
231  LOG((3, "%s: ncid 0x%x varid %d mem_type %d", __func__, ncid,
232  varid, mem_type));
233 
234  /* Find info for this file, group, and h5 info. */
235  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
236  return retval;
237  assert(h5 && grp);
238 
239  /* Check varid */
240  if (varid != NC_GLOBAL)
241  {
242  if (!(var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid)))
243  return NC_ENOTVAR;
244  assert(var->hdr.id == varid);
245  }
246 
247  /* Name is required. */
248  if (!name)
249  return NC_EBADNAME;
250 
251  /* Normalize name. */
252  if ((retval = nc4_normalize_name(name, norm_name)))
253  return retval;
254 
255  return nc4_get_att_ptrs(h5, grp, var, norm_name, xtype, mem_type, lenp,
256  attnum, data);
257 }
258 
273 int
274 NC4_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
275  size_t *lenp)
276 {
277  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
278  return nc4_get_att(ncid, varid, name, xtypep, NC_NAT, lenp, NULL, NULL);
279 }
280 
292 int
293 NC4_inq_attid(int ncid, int varid, const char *name, int *attnump)
294 {
295  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
296  return nc4_get_att(ncid, varid, name, NULL, NC_NAT, NULL, attnump, NULL);
297 }
298 
311 int
312 NC4_inq_attname(int ncid, int varid, int attnum, char *name)
313 {
314  NC_ATT_INFO_T *att;
315  int retval;
316 
317  LOG((2, "nc_inq_attname: ncid 0x%x varid %d attnum %d", ncid, varid,
318  attnum));
319 
320  /* Find the attribute metadata. */
321  if ((retval = nc4_find_nc_att(ncid, varid, NULL, attnum, &att)))
322  return retval;
323 
324  /* Get the name. */
325  if (name)
326  strcpy(name, att->hdr.name);
327 
328  return NC_NOERR;
329 }
330 
344 int
345 NC4_get_att(int ncid, int varid, const char *name, void *value, nc_type memtype)
346 {
347  return nc4_get_att(ncid, varid, name, NULL, memtype, NULL, NULL, value);
348 }
#define NC_ECHAR
Attempt to convert between text & numbers.
Definition: netcdf.h:429
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:35
#define NC_NAT
Not A Type.
Definition: netcdf.h:34
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:42
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:448
EXTERNL int nc_copy_data(int ncid, nc_type xtypeid, const void *memory, size_t count, void *copy)
Copy vector of arbitrary type instances.
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition: netcdf.h:254
#define NC_ENOTVAR
Variable not found.
Definition: netcdf.h:422
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:140
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:281
#define NC_NOERR
No Error.
Definition: netcdf.h:368
#define NC_NOQUANTIZE
No quantization in use.
Definition: netcdf.h:335
#define NC_EBADNAME
Attribute or variable name contains illegal characters.
Definition: netcdf.h:440
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:36
#define NC_ERANGE
Math result not representable.
Definition: netcdf.h:447
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:25