NetCDF  4.6.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 "hdf5internal.h"
22 #include "nc4dispatch.h"
23 #include "ncdispatch.h"
24 
42 static int
43 nc4_get_att_special(NC_FILE_INFO_T* h5, const char* name,
44  nc_type* filetypep, nc_type mem_type, size_t* lenp,
45  int* attnump, void* data)
46 {
47  /* Fail if asking for att id */
48  if(attnump)
49  return NC_EATTMETA;
50 
51  if(strcmp(name,NCPROPS)==0) {
52  char* propdata = NULL;
53  int stat = NC_NOERR;
54  int len;
55  if(h5->provenance->propattr.version == 0)
56  return NC_ENOTATT;
57  if(mem_type == NC_NAT) mem_type = NC_CHAR;
58  if(mem_type != NC_CHAR)
59  return NC_ECHAR;
60  if(filetypep) *filetypep = NC_CHAR;
61  stat = NC4_buildpropinfo(&h5->provenance->propattr, &propdata);
62  if(stat != NC_NOERR) return stat;
63  len = strlen(propdata);
64  if(lenp) *lenp = len;
65  if(data) strncpy((char*)data,propdata,len+1);
66  free(propdata);
67  } else if(strcmp(name,ISNETCDF4ATT)==0
68  || strcmp(name,SUPERBLOCKATT)==0) {
69  unsigned long long iv = 0;
70  if(filetypep) *filetypep = NC_INT;
71  if(lenp) *lenp = 1;
72  if(strcmp(name,SUPERBLOCKATT)==0)
73  iv = (unsigned long long)h5->provenance->superblockversion;
74  else /* strcmp(name,ISNETCDF4ATT)==0 */
75  iv = NC4_isnetcdf4(h5);
76  if(mem_type == NC_NAT) mem_type = NC_INT;
77  if(data)
78  switch (mem_type) {
79  case NC_BYTE: *((char*)data) = (char)iv; break;
80  case NC_SHORT: *((short*)data) = (short)iv; break;
81  case NC_INT: *((int*)data) = (int)iv; break;
82  case NC_UBYTE: *((unsigned char*)data) = (unsigned char)iv; break;
83  case NC_USHORT: *((unsigned short*)data) = (unsigned short)iv; break;
84  case NC_UINT: *((unsigned int*)data) = (unsigned int)iv; break;
85  case NC_INT64: *((long long*)data) = (long long)iv; break;
86  case NC_UINT64: *((unsigned long long*)data) = (unsigned long long)iv; break;
87  default:
88  return NC_ERANGE;
89  }
90  }
91  return NC_NOERR;
92 }
93 
112 static int
113 nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
114  nc_type mem_type, size_t *lenp, int *attnum, void *data)
115 {
116  NC *nc;
117  NC_GRP_INFO_T *grp;
118  NC_FILE_INFO_T *h5;
119  NC_ATT_INFO_T *att = NULL;
120  NC_VAR_INFO_T *var;
121  int my_attnum = -1;
122  int need_to_convert = 0;
123  int range_error = NC_NOERR;
124  void *bufr = NULL;
125  size_t type_size;
126  char norm_name[NC_MAX_NAME + 1];
127  int i;
128  int retval;
129 
130  if (attnum)
131  my_attnum = *attnum;
132 
133  LOG((3, "%s: ncid 0x%x varid %d name %s attnum %d mem_type %d",
134  __func__, ncid, varid, name, my_attnum, mem_type));
135 
136  /* Find info for this file, group, and h5 info. */
137  if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
138  return retval;
139 
140  /* Check varid */
141  if (varid != NC_GLOBAL)
142  {
143  if (!(var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid)))
144  return NC_ENOTVAR;
145  assert(var->hdr.id == varid);
146  }
147 
148  if (name == NULL)
149  BAIL(NC_EBADNAME);
150 
151  /* Normalize name. */
152  if ((retval = nc4_normalize_name(name, norm_name)))
153  BAIL(retval);
154 
155  /* Read the atts for this group/var, if they have not been read. */
156  if (varid == NC_GLOBAL)
157  {
158  if (grp->atts_not_read)
159  if ((retval = nc4_read_atts(grp, NULL)))
160  return retval;
161  }
162  else
163  {
164  if (var->atts_not_read)
165  if ((retval = nc4_read_atts(grp, var)))
166  return retval;
167  }
168 
169  /* If this is one of the reserved atts, use nc_get_att_special. */
170  if (nc->ext_ncid == ncid && varid == NC_GLOBAL) {
171  const NC_reservedatt* ra = NC_findreserved(norm_name);
172  if(ra != NULL && (ra->flags & NAMEONLYFLAG))
173  return nc4_get_att_special(h5, norm_name, xtype, mem_type, lenp, attnum, data);
174  }
175 
176  /* Find the attribute, if it exists. */
177  if ((retval = nc4_find_grp_att(grp, varid, norm_name, my_attnum, &att)))
178  return retval;
179 
180  /* If mem_type is NC_NAT, it means we want to use the attribute's
181  * file type as the mem type as well. */
182  if (mem_type == NC_NAT)
183  mem_type = att->nc_typeid;
184 
185  /* If the attribute is NC_CHAR, and the mem_type isn't, or vice
186  * versa, that's a freakish attempt to convert text to
187  * numbers. Some pervert out there is trying to pull a fast one!
188  * Send him an NC_ECHAR error. */
189  if (data && att->len)
190  if ((att->nc_typeid == NC_CHAR && mem_type != NC_CHAR) ||
191  (att->nc_typeid != NC_CHAR && mem_type == NC_CHAR))
192  BAIL(NC_ECHAR); /* take that, you freak! */
193 
194  /* Copy the info. */
195  if (lenp)
196  *lenp = att->len;
197  if (xtype)
198  *xtype = att->nc_typeid;
199  if (attnum) {
200  *attnum = att->hdr.id;
201  }
202 
203  /* Zero len attributes are easy to read! */
204  if (!att->len)
205  BAIL(NC_NOERR);
206 
207  /* Later on, we will need to know the size of this type. */
208  if ((retval = nc4_get_typelen_mem(h5, mem_type, &type_size)))
209  BAIL(retval);
210 
211  /* We may have to convert data. Treat NC_CHAR the same as
212  * NC_UBYTE. If the mem_type is NAT, don't try any conversion - use
213  * the attribute's type. */
214  if (data && att->len && mem_type != att->nc_typeid &&
215  mem_type != NC_NAT &&
216  !(mem_type == NC_CHAR &&
217  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE)))
218  {
219  if (!(bufr = malloc((size_t)(att->len * type_size))))
220  BAIL(NC_ENOMEM);
221  need_to_convert++;
222  if ((retval = nc4_convert_type(att->data, bufr, att->nc_typeid,
223  mem_type, (size_t)att->len, &range_error,
224  NULL, (h5->cmode & NC_CLASSIC_MODEL))))
225  BAIL(retval);
226 
227  /* For strict netcdf-3 rules, ignore erange errors between UBYTE
228  * and BYTE types. */
229  if ((h5->cmode & NC_CLASSIC_MODEL) &&
230  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE) &&
231  (mem_type == NC_UBYTE || mem_type == NC_BYTE) &&
232  range_error)
233  range_error = 0;
234  }
235  else
236  {
237  bufr = att->data;
238  }
239 
240  /* If the caller wants data, copy it for him. If he hasn't
241  allocated enough memory for it, he will burn in segmentation
242  fault hell, writhing with the agony of undiscovered memory
243  bugs! */
244  if (data)
245  {
246  if (att->vldata)
247  {
248  size_t base_typelen;
249  hvl_t *vldest = data;
250  NC_TYPE_INFO_T *type;
251 
252  /* Get the type object for the attribute's type */
253  if ((retval = nc4_find_type(h5, att->nc_typeid, &type)))
254  BAIL(retval);
255 
256  /* Retrieve the size of the base type */
257  if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, &base_typelen)))
258  BAIL(retval);
259 
260  for (i = 0; i < att->len; i++)
261  {
262  vldest[i].len = att->vldata[i].len;
263  if (!(vldest[i].p = malloc(vldest[i].len * base_typelen)))
264  BAIL(NC_ENOMEM);
265  memcpy(vldest[i].p, att->vldata[i].p, vldest[i].len * base_typelen);
266  }
267  }
268  else if (att->stdata)
269  {
270  for (i = 0; i < att->len; i++)
271  {
272  /* Check for NULL pointer for string (valid in HDF5) */
273  if(att->stdata[i])
274  {
275  if (!(((char **)data)[i] = strdup(att->stdata[i])))
276  BAIL(NC_ENOMEM);
277  }
278  else
279  ((char **)data)[i] = att->stdata[i];
280  }
281  }
282  else
283  {
284  memcpy(data, bufr, (size_t)(att->len * type_size));
285  }
286  }
287 
288 exit:
289  if (need_to_convert)
290  free(bufr);
291  if (range_error)
292  retval = NC_ERANGE;
293  return retval;
294 }
295 
310 int
311 NC4_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
312  size_t *lenp)
313 {
314  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
315  return nc4_get_att(ncid, varid, name, xtypep, NC_NAT, lenp, NULL, NULL);
316 }
317 
329 int
330 NC4_inq_attid(int ncid, int varid, const char *name, int *attnump)
331 {
332  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
333  return nc4_get_att(ncid, varid, name, NULL, NC_NAT, NULL, attnump, NULL);
334 }
335 
336 
349 int
350 NC4_inq_attname(int ncid, int varid, int attnum, char *name)
351 {
352  NC_ATT_INFO_T *att;
353  int retval;
354 
355  LOG((2, "nc_inq_attname: ncid 0x%x varid %d attnum %d", ncid, varid,
356  attnum));
357 
358  /* Find the attribute metadata. */
359  if ((retval = nc4_find_nc_att(ncid, varid, NULL, attnum, &att)))
360  return retval;
361 
362  /* Get the name. */
363  if (name)
364  strcpy(name, att->hdr.name);
365 
366  return NC_NOERR;
367 }
368 
382 int
383 NC4_get_att(int ncid, int varid, const char *name, void *value, nc_type memtype)
384 {
385  return nc4_get_att(ncid, varid, name, NULL, memtype, NULL, NULL, value);
386 }
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:402
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:35
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:41
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:137
#define NC_ERANGE
Math result not representable.
Definition: netcdf.h:401
#define NC_UINT
unsigned 4-byte int
Definition: netcdf.h:43
#define NC_INT64
signed 8-byte int
Definition: netcdf.h:44
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:24
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:34
#define NC_EATTMETA
Problem with attribute metadata.
Definition: netcdf.h:441
#define NC_EBADNAME
Attribute or variable name contains illegal characters.
Definition: netcdf.h:394
#define NC_INT
signed 4 byte integer
Definition: netcdf.h:37
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:272
#define NC_NAT
Not A Type.
Definition: netcdf.h:33
#define NC_USHORT
unsigned 2-byte int
Definition: netcdf.h:42
#define NC_SHORT
signed 2 byte integer
Definition: netcdf.h:36
#define NC_ENOTVAR
Variable not found.
Definition: netcdf.h:376
#define NC_NOERR
No Error.
Definition: netcdf.h:322
#define NC_ECHAR
Attempt to convert between text & numbers.
Definition: netcdf.h:383
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition: netcdf.h:245
#define NC_ENOTATT
Attribute not found.
Definition: netcdf.h:362
#define NC_UINT64
unsigned 8-byte int
Definition: netcdf.h:45

Return to the Main Unidata NetCDF page.
Generated on Tue Nov 20 2018 06:04:35 for NetCDF. NetCDF is a Unidata library.