OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_attr.c
Go to the documentation of this file.
1 #ifdef IRIX
2 #include <ieeefp.h>
3 #endif
4 
5 #include <math.h>
6 #include "fmt_check.h"
7 
8 extern int fmt_status; /* format checking status, see fmt_check */
9 
10 int get_attr(int32 fid, attr_str attr, u_data *value, int *d_count)
11 /*******************************************************************
12 
13  get_attr
14 
15  purpose: for a particular attribute, check the existance of it
16  in the dataset and make sure it has the specified
17  attribute name, number type and count. If so,
18  read the attribute into the data area
19 
20  Returns type: int - 0 if all went well,
21  -1 can't find the attribute
22  -2 bad match with name, number type or count
23  -3 unable to read the data
24 
25  Parameters: (in calling order)
26  Type Name I/O Description
27  ---- ---- --- -----------
28  int32 fid I file id or sds id
29  attr_str attr I attribute description
30  structure.
31  u_data * value O returned data structure
32  int* d_count O data item count read
33 
34  Modification history:
35  Programmer Date Description of change
36  ---------- ---- ---------------------
37  W. Robinson 27-Jan-1995 Original development
38  W. Robinson 30-Jun-1995 assure that only 3000 bytes of
39  attribute data are read
40  W. Robinson 30-Jun-1995 set fmt_status if problems
41  W. Robinson 4-Oct-1995 save actual count (a_count) for
42  printing
43  W. Robinson 20-Nov-1995 add check for strings so they have
44  only 1 null at the end (str_chk)
45  L. Kumar 19-Dec-1995 after gets back from str_chk, if the
46  string lack a null, place a null at
47  the end of string
48  W. Robinson 17-Sep-1996 increase the string handeling
49  capability to 66000 bytes (enough
50  for HDF 4.0)
51  W. Robinson 26-Sep-1996 enable attribute range checking
52  W. Robinson 31-Oct-1996 upgrade to handle float64 data type
53  W. Robinson 31-May-2000 check the floats for NaN if read and
54  the doubles to be finite
55  W. Robinson 15-Mar-2001 update for a linux array size change
56  (hope it always works)
57  W. Robinson 3 Feb 2010 allow a small range in float attrib
58  value checking
59 
60  *******************************************************************/
61  {
62  int i;
63  int32 attr_index;
64  char a_name[200], *temp;
65  int32 a_n_type, a_count;
66 
67  void chk_str(attr_str, char *, int32);
68 
69  if ((attr_index = SDfindattr(fid, attr.access_nm))
70  == -1) {
71  printf("**** object: '%s', Error trying to get attribute '%s'\n",
72  attr.obj_nm, attr.access_nm);
73  fmt_status = fmt_status | 2;
74  return -1;
75  }
76  /*
77  * Call SDattrinfo to get the info on this attribute
78  */
79  if (SDattrinfo(fid, attr_index, a_name, &a_n_type, &a_count)
80  == -1) {
81  printf("**** Error in SDattrinfo for object: '%s', attribute: '%s'\n",
82  attr.obj_nm, attr.access_nm);
83  fmt_status = fmt_status | 2;
84  return -4;
85  }
86  /*
87  * put actual count in output variable
88  */
89  *d_count = a_count;
90 
91  /*
92  * Check the name, number type and count
93  */
94  i = 0;
95  if (strcmp(a_name, attr.int_nm) != 0) {
96  printf(
97  "**** object: '%s', attribute: '%s', difference in attribute name found\n",
98  attr.obj_nm, attr.access_nm);
99  printf("expected: '%s', read: '%s'\n", attr.int_nm, a_name);
100  fmt_status = fmt_status | 2;
101  i = 1;
102  }
103  if (a_n_type != attr.type) {
104  printf(
105  "**** object: '%s', attribute: '%s', difference in number type found\n",
106  attr.obj_nm, attr.access_nm);
107  printf("expected: %d, read: %d\n", attr.type, a_n_type);
108  fmt_status = fmt_status | 2;
109  i = 1;
110  }
111  if (attr.count > 0 && a_count != attr.count) {
112  printf("**** object: '%s', attribute: '%s', difference in count found\n",
113  attr.obj_nm, attr.access_nm);
114  printf("expected: %d, read: %d\n", attr.count, a_count);
115  fmt_status = fmt_status | 2;
116  i = 1;
117  }
118  if (i != 0) return -2;
119  /*
120  * read in the attribute
121  */
122  if (attr.read != ATT_RD_NOREAD) {
123  /*
124  * in the event the attribute gets larger than the # bytes
125  * in value (a generous 66000 bytes!), allocate a temp read area
126  * and transfer the first 66000 bytes
127  * ** Use variable FMT_8BLEN for the 66000 **
128  */
129  if (a_count * DFKNTsize(a_n_type) >= FMT_8BLEN * 8) {
130  printf("**** object: '%s', attribute: '%s' has excessive count of \n",
131  attr.obj_nm, attr.access_nm);
132  printf("%d items. Truncated list of bytes will be used\n",
133  a_count);
134  /* remove this as a problem
135  fmt_status = fmt_status | 2;
136  */
137 
138  temp = (char *) malloc(a_count * DFKNTsize(a_n_type));
139  if (SDreadattr(fid, attr_index, temp) == -1) {
140  printf("**** object: '%s', attribute: '%s', Error reading data\n",
141  attr.obj_nm, attr.access_nm);
142  return -3;
143  fmt_status = fmt_status | 2;
144  }
145  /*
146  * check for null at end only
147  */
148  chk_str(attr, temp, a_count);
149 
150  memcpy(value->chr, temp, FMT_8BLEN);
151  free(temp);
152  } else {
153  if (SDreadattr(fid, attr_index, value->chr) == -1) {
154  printf("**** object: '%s', attribute: '%s', Error reading data\n",
155  attr.obj_nm, attr.access_nm);
156  fmt_status = fmt_status | 2;
157  return -3;
158  }
159  /*
160  * check for null at end only
161  */
162  chk_str(attr, value->chr, a_count);
163  }
164  /*
165  * any read-in floats can be checked for NaN status and the doubles can
166  * be checked for finite status
167  */
168  switch (attr.type) {
169  case DFNT_FLOAT32:
170  for (i = 0; i < attr.count; i++) {
171  if (isnan(value->f32[i])) {
172  printf(
173  "**** object: '%s', attribute '%s'[%d]\n",
174  attr.obj_nm, attr.access_nm, i);
175  printf("is not a number (NaN)\n");
176  fmt_status = fmt_status | 2;
177  }
178  }
179  break;
180  case DFNT_FLOAT64:
181  for (i = 0; i < attr.count; i++) {
182  if (!isfinite(attr.data.f64[i])) {
183  printf(
184  "**** object: '%s', attribute '%s'[%d]\n",
185  attr.obj_nm, attr.access_nm, i);
186  printf("is not a number (NaN) or not finite\n");
187  fmt_status = fmt_status | 2;
188  }
189  }
190  break;
191  }
192  /*
193  * Check the constant attribute values (read = READ_ONE_VAL)
194  * and handle variables in a range to calling routine
195  */
196  if (attr.read == ATT_RD_READ_ONE_VAL) {
197  switch (attr.type) {
198  case DFNT_CHAR:
199  if (value->chr[a_count - 1] != 0) /* LK */
200  value->chr[a_count] = 0; /* LK */
201  if (strcmp(value->chr, attr.data.chr) != 0) {
202  printf("**** object: '%s', difference in attribute '%s'\n",
203  attr.obj_nm, attr.access_nm);
204  printf("expected value: '%s'\nread value : '%s'\n",
205  attr.data.chr, value->chr);
206  fmt_status = fmt_status | 2;
207  }
208  break;
209  case DFNT_FLOAT32:
210  for (i = 0; i < attr.count; i++) {
211  if ((value->f32[i] < attr.data.f32[i] -
212  fabsf(attr.data.f32[i]) * ERR_FRAC_F32) ||
213  (value->f32[i] > attr.data.f32[i] +
214  fabsf(attr.data.f32[i]) * ERR_FRAC_F32)) {
215  printf(
216  "**** object: '%s', difference in attribute '%s'[%d]\n",
217  attr.obj_nm, attr.access_nm, i);
218  printf("expected value: %f\nread value: %f\n",
219  attr.data.f32[i], value->f32[i]);
220  fmt_status = fmt_status | 2;
221  }
222  }
223  break;
224  case DFNT_FLOAT64:
225  for (i = 0; i < attr.count; i++) {
226  if ((value->f64[i] < attr.data.f64[i] -
227  fabs(attr.data.f64[i]) * ERR_FRAC_F64) ||
228  (value->f64[i] > attr.data.f64[i] +
229  fabs(attr.data.f64[i]) * ERR_FRAC_F64)) {
230  printf(
231  "**** object: '%s', difference in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
232  printf("expected value: %f\nread value: %f\n",
233  attr.data.f64[i], value->f64[i]);
234  fmt_status = fmt_status | 2;
235  }
236  }
237  break;
238  case DFNT_INT8:
239  for (i = 0; i < attr.count; i++) {
240  if (value->i8[i] != attr.data.i8[i]) {
241  printf(
242  "**** object: '%s', difference in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
243  printf("expected value: %d\nread value: %d\n",
244  attr.data.i8[i], value->i8[i]);
245  fmt_status = fmt_status | 2;
246  }
247  }
248  break;
249  case DFNT_UINT8:
250  for (i = 0; i < attr.count; i++) {
251  if (value->ui8[i] != attr.data.ui8[i]) {
252  printf(
253  "**** object: '%s', difference in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
254  printf("expected value: %d\nread value: %d\n",
255  attr.data.ui8[i], value->ui8[i]);
256  fmt_status = fmt_status | 2;
257  }
258  }
259  break;
260  case DFNT_INT16:
261  for (i = 0; i < attr.count; i++) {
262  if (value->i16[i] != attr.data.i16[i]) {
263  printf(
264  "**** object: '%s', difference in attribute '%s'[%d]\n",
265  attr.obj_nm, attr.access_nm, i);
266  printf("expected value: %d\nread value: %d\n",
267  attr.data.i16[i], value->i16[i]);
268  fmt_status = fmt_status | 2;
269  }
270  }
271  break;
272  case DFNT_INT32:
273  for (i = 0; i < attr.count; i++) {
274  if (value->i32[i] != attr.data.i32[i]) {
275  printf(
276  "**** object: '%s', difference in attribute '%s'[%d]\n",
277  attr.obj_nm, attr.access_nm, i);
278  printf("expected value: %d\nread value: %d\n",
279  attr.data.i32[i], value->i32[i]);
280  fmt_status = fmt_status | 2;
281  }
282  }
283  break;
284  default:
285  printf("************* DEFAULT CASE OF VALUE CHECKING\n");
286  printf("Program error\n");
287  fmt_status = fmt_status | 1;
288  break;
289  }
290  } else if (attr.read == ATT_RD_READ_INCLUSIVE) {
291  switch (attr.type) {
292  case DFNT_CHAR:
293  if (value->chr[a_count - 1] != 0) /* LK */
294  value->chr[a_count] = 0; /* LK */
295  if (strcmp(value->chr, attr.data.chr) != 0) {
296  printf("**** object: '%s', difference in attribute '%s'\n",
297  attr.obj_nm, attr.access_nm);
298  printf("expected value: '%s'\nread value : '%s'\n",
299  attr.data.chr, value->chr);
300  fmt_status = fmt_status | 2;
301  }
302  break;
303  case DFNT_FLOAT32:
304  for (i = 0; i < attr.count; i++) {
305  if (value->f32[i] < attr.data.f32[0] ||
306  value->f32[i] > attr.data.f32[1]) {
307  printf(
308  "**** object: '%s', outside range in attribute '%s'[%d]\n",
309  attr.obj_nm, attr.access_nm, i);
310  printf("valid range: %f - %f\nread value: %f\n",
311  attr.data.f32[0], attr.data.f32[1], value->f32[i]);
312  fmt_status = fmt_status | 2;
313  }
314  }
315  break;
316  case DFNT_FLOAT64:
317  for (i = 0; i < attr.count; i++) {
318  if (value->f64[i] < attr.data.f64[0] ||
319  value->f64[i] > attr.data.f64[1]) {
320  printf(
321  "**** object: '%s', outside range in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
322  printf("valid range: %f - %f\nread value: %f\n",
323  attr.data.f64[0], attr.data.f64[1], value->f64[i]);
324  fmt_status = fmt_status | 2;
325  }
326  }
327  break;
328  case DFNT_INT8:
329  for (i = 0; i < attr.count; i++) {
330  if (value->i8[i] < attr.data.i8[0] ||
331  value->i8[i] > attr.data.i8[1]) {
332  printf(
333  "**** object: '%s', outside range in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
334  printf("valid range: %d - %d\nread value: %d\n",
335  attr.data.i8[0], attr.data.i8[1], value->i8[i]);
336  fmt_status = fmt_status | 2;
337  }
338  }
339  break;
340  case DFNT_UINT8:
341  for (i = 0; i < attr.count; i++) {
342  if (value->ui8[i] < attr.data.ui8[0] ||
343  value->ui8[i] > attr.data.ui8[1]) {
344  printf(
345  "**** object: '%s', outside range in attribute '%s'[%d]\n", attr.obj_nm, attr.access_nm, i);
346  printf("valid range: %d - %d\nread value: %d\n",
347  attr.data.ui8[0], attr.data.ui8[1], value->ui8[i]);
348  fmt_status = fmt_status | 2;
349  }
350  }
351  break;
352  case DFNT_INT16:
353  for (i = 0; i < attr.count; i++) {
354  if (value->i16[i] < attr.data.i16[0] ||
355  value->i16[i] > attr.data.i16[1]) {
356  printf(
357  "**** object: '%s', outside range in attribute '%s'[%d]\n",
358  attr.obj_nm, attr.access_nm, i);
359  printf("valid range: %d - %d\nread value: %d\n",
360  attr.data.i16[0], attr.data.i16[1], value->i16[i]);
361  fmt_status = fmt_status | 2;
362  }
363  }
364  break;
365  case DFNT_INT32:
366  for (i = 0; i < attr.count; i++) {
367  if (value->i32[i] < attr.data.i32[0] ||
368  value->i32[i] > attr.data.i32[1]) {
369  printf(
370  "**** object: '%s', outside range in attribute '%s'[%d]\n",
371  attr.obj_nm, attr.access_nm, i);
372  printf("valid range: %d - %d\nread value: %d\n",
373  attr.data.i32[0], attr.data.i32[1], value->i32[i]);
374  fmt_status = fmt_status | 2;
375  }
376  }
377  break;
378  default:
379  printf("************* DEFAULT CASE OF VALUE CHECKING\n");
380  printf("Program error\n");
381  fmt_status = fmt_status | 1;
382  break;
383  }
384  }
385  }
386  return 0;
387 }
int32 value
Definition: Granule.c:1235
@ ATT_RD_NOREAD
Definition: fmt_check.h:47
int get_attr(int32 fid, attr_str attr, u_data *value, int *d_count)
Definition: get_attr.c:10
void chk_str(attr_str attr, char *str, int32 len)
Definition: chk_str.c:4
@ ATT_RD_READ_ONE_VAL
Definition: fmt_check.h:47
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
#define ERR_FRAC_F32
Definition: fmt_check.h:201
#define ERR_FRAC_F64
Definition: fmt_check.h:202
int fmt_status
Definition: fmt_check.c:7
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
#define FMT_8BLEN
Definition: fmt_check.h:38
@ ATT_RD_READ_INCLUSIVE
Definition: fmt_check.h:48
#define fabs(a)
Definition: misc.h:93
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
int i
Definition: decode_rs.h:71