NetCDF  4.9.3
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 
46 int
47 nc4_get_att_ptrs(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var,
48  const char *name, nc_type *xtype, nc_type mem_type,
49  size_t *lenp, int *attnum, void *data)
50 {
51  NC_ATT_INFO_T *att = NULL;
52  int my_attnum = -1;
53  int need_to_convert = 0;
54  int range_error = NC_NOERR;
55  void *bufr = NULL;
56  size_t type_size;
57  int varid;
58  int retval;
59 
60  LOG((3, "%s: mem_type %d", __func__, mem_type));
61 
62  /* Get the varid, or NC_GLOBAL. */
63  varid = var ? var->hdr.id : NC_GLOBAL;
64 
65  if (attnum)
66  my_attnum = *attnum;
67 
68  if (name == NULL)
69  BAIL(NC_EBADNAME);
70 
71  /* Find the attribute, if it exists. */
72  if ((retval = nc4_find_grp_att(grp, varid, name, my_attnum, &att)))
73  return retval;
74 
75  /* If mem_type is NC_NAT, it means we want to use the attribute's
76  * file type as the mem type as well. */
77  if (mem_type == NC_NAT)
78  mem_type = att->nc_typeid;
79 
80  /* If the attribute is NC_CHAR, and the mem_type isn't, or vice
81  * versa, that's a freakish attempt to convert text to
82  * numbers. Some pervert out there is trying to pull a fast one!
83  * Send him an NC_ECHAR error. */
84  if (data && att->len)
85  if ((att->nc_typeid == NC_CHAR && mem_type != NC_CHAR) ||
86  (att->nc_typeid != NC_CHAR && mem_type == NC_CHAR))
87  BAIL(NC_ECHAR); /* take that, you freak! */
88 
89  /* Copy the info. */
90  if (lenp)
91  *lenp = att->len;
92  if (xtype)
93  *xtype = att->nc_typeid;
94  if (attnum) {
95  *attnum = att->hdr.id;
96  }
97 
98  /* Zero len attributes are easy to read! */
99  if (!att->len)
100  BAIL(NC_NOERR);
101 
102  /* Later on, we will need to know the size of this type. */
103  if ((retval = nc4_get_typelen_mem(h5, mem_type, &type_size)))
104  BAIL(retval);
105 
106  /* We may have to convert data. Treat NC_CHAR the same as
107  * NC_UBYTE. If the mem_type is NAT, don't try any conversion - use
108  * the attribute's type. */
109  if (data && att->len && mem_type != att->nc_typeid &&
110  mem_type != NC_NAT &&
111  !(mem_type == NC_CHAR &&
112  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE)))
113  {
114  if (!(bufr = malloc((size_t)(att->len) * type_size)))
115  BAIL(NC_ENOMEM);
116  need_to_convert++;
117  if ((retval = nc4_convert_type(att->data, bufr, att->nc_typeid,
118  mem_type, (size_t)att->len, &range_error,
119  NULL, (h5->cmode & NC_CLASSIC_MODEL),
120  NC_NOQUANTIZE, 0)))
121  BAIL(retval);
122 
123  /* For strict netcdf-3 rules, ignore erange errors between UBYTE
124  * and BYTE types. */
125  if ((h5->cmode & NC_CLASSIC_MODEL) &&
126  (att->nc_typeid == NC_UBYTE || att->nc_typeid == NC_BYTE) &&
127  (mem_type == NC_UBYTE || mem_type == NC_BYTE) &&
128  range_error)
129  range_error = 0;
130  }
131  else
132  {
133  bufr = att->data;
134  }
135 
136  /* If the caller wants data, copy it for him. If he hasn't
137  allocated enough memory for it, he will burn in segmentation
138  fault hell, writhing with the agony of undiscovered memory
139  bugs! */
140  if (data)
141  {
142  {
143  if((retval = NC_copy_data(h5->controller,mem_type,bufr,att->len,data)))
144  BAIL(retval);
145  }
146  }
147 
148 exit:
149  if (need_to_convert)
150  free(bufr);
151  if (range_error)
152  retval = NC_ERANGE;
153  return retval;
154 }
155 
177 int
178 nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
179  nc_type mem_type, size_t *lenp, int *attnum, void *data)
180 {
181  NC_FILE_INFO_T *h5;
182  NC_GRP_INFO_T *grp;
183  NC_VAR_INFO_T *var = NULL;
184  char norm_name[NC_MAX_NAME + 1];
185  int retval;
186 
187  LOG((3, "%s: ncid 0x%x varid %d mem_type %d", __func__, ncid,
188  varid, mem_type));
189 
190  /* Find info for this file, group, and h5 info. */
191  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
192  return retval;
193  assert(h5 && grp);
194 
195  /* Check varid */
196  if (varid != NC_GLOBAL)
197  {
198  if (!(var = (NC_VAR_INFO_T*)ncindexith(grp->vars,(size_t)varid)))
199  return NC_ENOTVAR;
200  assert(var->hdr.id == varid);
201  }
202 
203  /* Name is required. */
204  if (!name)
205  return NC_EBADNAME;
206 
207  /* Normalize name. */
208  if ((retval = nc4_normalize_name(name, norm_name)))
209  return retval;
210 
211  return nc4_get_att_ptrs(h5, grp, var, norm_name, xtype, mem_type, lenp,
212  attnum, data);
213 }
214 
229 int
230 NC4_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
231  size_t *lenp)
232 {
233  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
234  return nc4_get_att(ncid, varid, name, xtypep, NC_NAT, lenp, NULL, NULL);
235 }
236 
248 int
249 NC4_inq_attid(int ncid, int varid, const char *name, int *attnump)
250 {
251  LOG((2, "%s: ncid 0x%x varid %d name %s", __func__, ncid, varid, name));
252  return nc4_get_att(ncid, varid, name, NULL, NC_NAT, NULL, attnump, NULL);
253 }
254 
267 int
268 NC4_inq_attname(int ncid, int varid, int attnum, char *name)
269 {
270  NC_ATT_INFO_T *att;
271  int retval;
272 
273  LOG((2, "nc_inq_attname: ncid 0x%x varid %d attnum %d", ncid, varid,
274  attnum));
275 
276  /* Find the attribute metadata. */
277  if ((retval = nc4_find_nc_att(ncid, varid, NULL, attnum, &att)))
278  return retval;
279 
280  /* Get the name. */
281  if (name)
282  strcpy(name, att->hdr.name);
283 
284  return NC_NOERR;
285 }
286 
300 int
301 NC4_get_att(int ncid, int varid, const char *name, void *value, nc_type memtype)
302 {
303  return nc4_get_att(ncid, varid, name, NULL, memtype, NULL, NULL, value);
304 }
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:458
#define NC_CHAR
ISO/ASCII character.
Definition: netcdf.h:36
#define NC_UBYTE
unsigned 1 byte int
Definition: netcdf.h:42
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:149
#define NC_ERANGE
Math result not representable.
Definition: netcdf.h:457
#define NC_NOQUANTIZE
No quantization in use.
Definition: netcdf.h:345
int nc_type
The nc_type type is just an int.
Definition: netcdf.h:25
#define NC_BYTE
signed 1 byte integer
Definition: netcdf.h:35
#define NC_EBADNAME
Attribute or variable name contains illegal characters.
Definition: netcdf.h:450
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:291
#define NC_NAT
Not A Type.
Definition: netcdf.h:34
#define NC_ENOTVAR
Variable not found.
Definition: netcdf.h:432
#define NC_NOERR
No Error.
Definition: netcdf.h:378
#define NC_ECHAR
Attempt to convert between text & numbers.
Definition: netcdf.h:439
#define NC_GLOBAL
Attribute id to put/get a global attribute.
Definition: netcdf.h:264