NetCDF 4.9.1
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
45int
46nc4_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
192exit:
193 if (need_to_convert)
194 free(bufr);
195 if (range_error)
196 retval = NC_ERANGE;
197 return retval;
198}
199
221int
222nc4_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
273int
274NC4_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
292int
293NC4_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
311int
312NC4_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
344int
345NC4_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