ocssw  1.0
/disk01/web/ocssw/build/src/auto_qc/fmt_check/get_attr.c (r8099/r7362)
Go to the documentation of this file.
00001 #ifdef IRIX
00002 #include <ieeefp.h>
00003 #endif
00004 
00005 #include <math.h>
00006 #include "fmt_check.h"
00007 
00008 extern int fmt_status;  /* format checking status, see fmt_check */
00009 
00010 int get_attr( int32 fid, attr_str attr, u_data *value, int *d_count )
00011 /*******************************************************************
00012 
00013    get_attr
00014 
00015    purpose: for a particular attribute, check the existance of it
00016             in the dataset and make sure it has the specified 
00017             attribute name, number type and count.  If so,
00018             read the attribute into the data area
00019 
00020    Returns type: int - 0 if all went well, 
00021                        -1 can't find the attribute
00022                        -2 bad match with name, number type or count
00023                        -3 unable to read the data
00024 
00025    Parameters: (in calling order)
00026       Type              Name            I/O     Description
00027       ----              ----            ---     -----------
00028       int32             fid              I      file id or sds id
00029       attr_str          attr             I      attribute description
00030                                                 structure. 
00031       u_data *          value            O      returned data structure
00032       int*              d_count          O      data item count read
00033 
00034    Modification history:
00035       Programmer        Date            Description of change
00036       ----------        ----            ---------------------
00037       W. Robinson       27-Jan-1995     Original development
00038       W. Robinson       30-Jun-1995     assure that only 3000 bytes of
00039                                         attribute data are read
00040       W. Robinson       30-Jun-1995     set fmt_status if problems
00041       W. Robinson       4-Oct-1995      save actual count (a_count) for
00042                                         printing
00043       W. Robinson       20-Nov-1995     add check for strings so they have 
00044                                         only 1 null at the end (str_chk)
00045       L. Kumar      19-Dec-1995     after gets back from str_chk, if the
00046                     string lack a null, place a null at
00047                     the end of string
00048       W. Robinson       17-Sep-1996     increase the string handeling 
00049                                         capability to 66000 bytes (enough 
00050                                         for HDF 4.0)
00051       W. Robinson       26-Sep-1996     enable attribute range checking
00052       W. Robinson       31-Oct-1996     upgrade to handle float64 data type
00053       W. Robinson       31-May-2000     check the floats for NaN if read and
00054                                         the doubles to be finite
00055       W. Robinson       15-Mar-2001     update for a linux array size change
00056                                         (hope it always works)
00057       W. Robinson       3 Feb 2010      allow a small range in float attrib
00058                                         value checking
00059 
00060 *******************************************************************/
00061 
00062    {
00063    int i, iatr;
00064    int32 attr_index, gain1[8], index, sds_id;
00065    char att_info_name[200], a_name[200], *temp;
00066    int32  att_info_numtyp, att_info_count, a_n_type, a_count;
00067 
00068    void chk_str( attr_str, char *, int32 );
00069 
00070    if( ( attr_index = SDfindattr( fid, attr.access_nm ) )
00071        == -1 )
00072       {
00073       printf( "**** object: '%s', Error trying to get attribute '%s'\n", 
00074              attr.obj_nm, attr.access_nm );
00075       fmt_status = fmt_status | 2;
00076       return -1;
00077       }
00078   /*
00079    *  Call SDattrinfo to get the info on this attribute
00080    */
00081    if( SDattrinfo( fid, attr_index, a_name, &a_n_type, &a_count )
00082           == -1 )
00083       {
00084       printf( "**** Error in SDattrinfo for object: '%s', attribute: '%s'\n", 
00085              attr.obj_nm, attr.access_nm );
00086       fmt_status = fmt_status | 2;
00087       return -4;
00088       }
00089   /*
00090    *  put actual count in output variable
00091    */
00092    *d_count = a_count;
00093 
00094   /*
00095    *  Check the name, number type and count
00096    */
00097    i = 0;
00098    if( strcmp( a_name, attr.int_nm ) != 0 )
00099       {
00100       printf( 
00101      "**** object: '%s', attribute: '%s', difference in attribute name found\n",
00102           attr.obj_nm, attr.access_nm );
00103       printf( "expected: '%s', read: '%s'\n", attr.int_nm, a_name );
00104       fmt_status = fmt_status | 2;
00105       i = 1;
00106       }
00107    if( a_n_type != attr.type )
00108       {
00109       printf( 
00110       "**** object: '%s', attribute: '%s', difference in number type found\n",
00111           attr.obj_nm, attr.access_nm );
00112       printf( "expected: %d, read: %d\n", attr.type, a_n_type );
00113       fmt_status = fmt_status | 2;
00114       i = 1;
00115       }
00116    if( attr.count > 0 && a_count != attr.count )
00117       {
00118       printf( "**** object: '%s', attribute: '%s', difference in count found\n",
00119           attr.obj_nm, attr.access_nm );
00120       printf( "expected: %d, read: %d\n", attr.count, a_count );
00121       fmt_status = fmt_status | 2;
00122       i = 1;
00123       }
00124    if( i != 0 ) return -2;
00125   /*
00126    *  read in the attribute
00127    */
00128    if( attr.read != ATT_RD_NOREAD )
00129       {
00130      /*
00131       *  in the event the attribute gets larger than the # bytes
00132       *  in value (a generous 66000 bytes!), allocate a temp read area
00133       *  and transfer the first 66000 bytes
00134       *   ** Use variable FMT_8BLEN for the 66000 **
00135       */
00136       if( a_count * DFKNTsize( a_n_type ) >= FMT_8BLEN * 8 )
00137          {
00138          printf( "**** object: '%s', attribute: '%s' has excessive count of \n",
00139          attr.obj_nm, attr.access_nm );
00140          printf( "%d items. Truncated list of bytes will be used\n", 
00141             a_count );
00142         /*   remove this as a problem
00143          fmt_status = fmt_status | 2;
00144          */
00145 
00146          temp = (char *) malloc( a_count * DFKNTsize( a_n_type ) );
00147          if( SDreadattr( fid, attr_index, temp ) == -1 )
00148             {
00149             printf( "**** object: '%s', attribute: '%s', Error reading data\n",
00150                attr.obj_nm, attr.access_nm);
00151             return -3;
00152             fmt_status = fmt_status | 2;
00153             }
00154         /*
00155          *  check for null at end only
00156          */
00157          chk_str( attr, temp, a_count );
00158 
00159          memcpy( value->chr, temp, FMT_8BLEN );
00160          free( temp );
00161          }
00162       else
00163          {
00164          if( SDreadattr( fid, attr_index, value->chr ) == -1 )
00165             {
00166             printf( "**** object: '%s', attribute: '%s', Error reading data\n", 
00167                attr.obj_nm, attr.access_nm);
00168             fmt_status = fmt_status | 2;
00169             return -3;
00170             }
00171         /*
00172          *  check for null at end only
00173          */
00174          chk_str( attr, value->chr, a_count );
00175          }
00176      /*
00177       *  any read-in floats can be checked for NaN status and the doubles can
00178       *  be checked for finite status
00179       */
00180       switch ( attr.type )
00181         {
00182         case DFNT_FLOAT32:
00183           for( i = 0; i < attr.count; i++ )
00184             {
00185             if( isnan( value->f32[i] ) )
00186               {
00187               printf(
00188                 "**** object: '%s', attribute '%s'[%d]\n",
00189                 attr.obj_nm, attr.access_nm, i );
00190               printf( "is not a number (NaN)\n" );
00191               fmt_status = fmt_status | 2;
00192               }
00193             }
00194           break;
00195         case DFNT_FLOAT64:
00196           for( i = 0; i < attr.count; i++ )
00197             {
00198             if( !finite( attr.data.f64[i] ) )
00199               {
00200               printf(
00201                 "**** object: '%s', attribute '%s'[%d]\n",
00202                 attr.obj_nm, attr.access_nm, i );
00203               printf( "is not a number (NaN) or not finite\n" );
00204               fmt_status = fmt_status | 2;
00205               }
00206             }
00207           break;
00208         }
00209      /*
00210       *  Check the constant attribute values (read = READ_ONE_VAL) 
00211       *  and handle variables in a range to calling routine
00212       */
00213       if( attr.read == ATT_RD_READ_ONE_VAL )
00214          {
00215          switch ( attr.type )
00216             {
00217             case DFNT_CHAR:
00218                if( value->chr[a_count-1] != 0 )     /* LK */
00219                    value->chr[a_count] = 0;         /* LK */
00220                if( strcmp( value->chr, attr.data.chr ) != 0 )
00221                   {
00222                   printf( "**** object: '%s', difference in attribute '%s'\n",
00223                      attr.obj_nm, attr.access_nm );
00224                   printf( "expected value: '%s'\nread value    : '%s'\n",
00225                      attr.data.chr, value->chr );
00226                   fmt_status = fmt_status | 2;
00227                   }
00228                break;
00229             case DFNT_FLOAT32:
00230                for( i = 0; i < attr.count; i++ )
00231                   {
00232                   if( ( value->f32[i] < attr.data.f32[i] -
00233                         fabsf( attr.data.f32[i] ) * ERR_FRAC_F32 ) ||
00234                       ( value->f32[i] > attr.data.f32[i] +
00235                         fabsf( attr.data.f32[i] ) * ERR_FRAC_F32 ) )
00236                      {
00237                      printf( 
00238                         "**** object: '%s', difference in attribute '%s'[%d]\n",
00239                           attr.obj_nm, attr.access_nm, i );
00240                      printf( "expected value: %f\nread value: %f\n",
00241                          attr.data.f32[i], value->f32[i] );
00242                      fmt_status = fmt_status | 2;
00243                      }
00244                   }
00245                break;
00246             case DFNT_FLOAT64:
00247                for( i = 0; i < attr.count; i++ )
00248                   {
00249                   if( ( value->f64[i] < attr.data.f64[i] -
00250                         fabs( attr.data.f64[i] ) * ERR_FRAC_F64 ) ||
00251                       ( value->f64[i] > attr.data.f64[i] +
00252                         fabs( attr.data.f64[i] ) * ERR_FRAC_F64 ) )
00253                      {
00254                      printf(
00255                         "**** object: '%s', difference in attribute '%s'[%d]\n",                          attr.obj_nm, attr.access_nm, i );
00256                      printf( "expected value: %f\nread value: %f\n",
00257                          attr.data.f64[i], value->f64[i] );
00258                      fmt_status = fmt_status | 2;
00259                      }
00260                   }
00261                break;
00262             case DFNT_INT8:
00263                for( i = 0; i < attr.count; i++ )
00264                   {
00265                   if( value->i8[i] != attr.data.i8[i] )
00266                      {
00267                      printf(
00268                         "**** object: '%s', difference in attribute '%s'[%d]\n",                        attr.obj_nm, attr.access_nm, i );
00269                      printf( "expected value: %d\nread value: %d\n",
00270                         attr.data.i8[i], value->i8[i] );
00271                      fmt_status = fmt_status | 2;
00272                      }
00273                   }
00274                break;
00275             case DFNT_UINT8:
00276                for( i = 0; i < attr.count; i++ )
00277                   {
00278                   if( value->ui8[i] != attr.data.ui8[i] )
00279                      {
00280                      printf(
00281                         "**** object: '%s', difference in attribute '%s'[%d]\n",                        attr.obj_nm, attr.access_nm, i );
00282                      printf( "expected value: %d\nread value: %d\n",
00283                         attr.data.ui8[i], value->ui8[i] );
00284                      fmt_status = fmt_status | 2;
00285                      }
00286                   }
00287                break;
00288             case DFNT_INT16:
00289                for( i = 0; i < attr.count; i++ )
00290                   {
00291                   if( value->i16[i] != attr.data.i16[i] )
00292                      {
00293                      printf( 
00294                         "**** object: '%s', difference in attribute '%s'[%d]\n",
00295                         attr.obj_nm, attr.access_nm, i );
00296                      printf( "expected value: %d\nread value: %d\n",
00297                         attr.data.i16[i], value->i16[i] );
00298                      fmt_status = fmt_status | 2;
00299                      }
00300                   }
00301                break;
00302             case DFNT_INT32:
00303                for( i = 0; i < attr.count; i++ )
00304                   {
00305                   if( value->i32[i] != attr.data.i32[i] )
00306                      {
00307                      printf( 
00308                         "**** object: '%s', difference in attribute '%s'[%d]\n",
00309                         attr.obj_nm, attr.access_nm, i );
00310                      printf( "expected value: %d\nread value: %d\n",
00311                         attr.data.i32[i], value->i32[i] );
00312                      fmt_status = fmt_status | 2;
00313                      }
00314                   }
00315                break;
00316             default:
00317                printf( "************* DEFAULT CASE OF VALUE CHECKING\n" );
00318                printf( "Program error\n" );
00319                fmt_status = fmt_status | 1;
00320                break;
00321             }
00322          }
00323       else if( attr.read == ATT_RD_READ_INCLUSIVE )
00324          {
00325          switch ( attr.type )
00326             {
00327             case DFNT_CHAR:
00328                if( value->chr[a_count-1] != 0 )              /* LK */
00329                    value->chr[a_count] = 0;                  /* LK */
00330                if( strcmp( value->chr, attr.data.chr ) != 0 )
00331                   {
00332                   printf( "**** object: '%s', difference in attribute '%s'\n",
00333                      attr.obj_nm, attr.access_nm );
00334                   printf( "expected value: '%s'\nread value    : '%s'\n",
00335                      attr.data.chr, value->chr );
00336                   fmt_status = fmt_status | 2;
00337                   }
00338                break;
00339             case DFNT_FLOAT32:
00340                for( i = 0; i < attr.count; i++ )
00341                   {
00342                   if( value->f32[i] < attr.data.f32[0]  ||
00343                       value->f32[i] > attr.data.f32[1]     )
00344                      {
00345                      printf( 
00346                      "**** object: '%s', outside range in attribute '%s'[%d]\n",
00347                           attr.obj_nm, attr.access_nm, i );
00348                      printf( "valid range: %f - %f\nread value: %f\n",
00349                          attr.data.f32[0], attr.data.f32[1], value->f32[i] );
00350                      fmt_status = fmt_status | 2;
00351                      }
00352                   }
00353                break;
00354             case DFNT_FLOAT64:
00355                for( i = 0; i < attr.count; i++ )
00356                   {
00357                   if( value->f64[i] < attr.data.f64[0]  ||
00358                       value->f64[i] > attr.data.f64[1]     )
00359                      {
00360                      printf(
00361                      "**** object: '%s', outside range in attribute '%s'[%d]\n",                          attr.obj_nm, attr.access_nm, i );
00362                      printf( "valid range: %f - %f\nread value: %f\n",
00363                          attr.data.f64[0], attr.data.f64[1], value->f64[i] );
00364                      fmt_status = fmt_status | 2;
00365                      }
00366                   }
00367                break;
00368             case DFNT_INT8:
00369                for( i = 0; i < attr.count; i++ )
00370                   {
00371                   if( value->i8[i] < attr.data.i8[0]  ||
00372                       value->i8[i] > attr.data.i8[1]      )
00373                      {
00374                      printf(
00375                      "**** object: '%s', outside range in attribute '%s'[%d]\n",                        attr.obj_nm, attr.access_nm, i );
00376                      printf( "valid range: %d - %d\nread value: %d\n",
00377                         attr.data.i8[0], attr.data.i8[1], value->i8[i] );
00378                      fmt_status = fmt_status | 2;
00379                      }
00380                   }
00381                break;
00382             case DFNT_UINT8:
00383                for( i = 0; i < attr.count; i++ )
00384                   {
00385                   if( value->ui8[i] < attr.data.ui8[0]   ||
00386                       value->ui8[i] > attr.data.ui8[1]      )
00387                      {
00388                      printf(
00389                      "**** object: '%s', outside range in attribute '%s'[%d]\n",                        attr.obj_nm, attr.access_nm, i );
00390                      printf( "valid range: %d - %d\nread value: %d\n",
00391                         attr.data.ui8[0], attr.data.ui8[1], value->ui8[i] );
00392                      fmt_status = fmt_status | 2;
00393                      }
00394                   }
00395                break;
00396             case DFNT_INT16:
00397                for( i = 0; i < attr.count; i++ )
00398                   {
00399                   if( value->i16[i] < attr.data.i16[0]   ||
00400                       value->i16[i] > attr.data.i16[1]      )
00401                      {
00402                      printf( 
00403                      "**** object: '%s', outside range in attribute '%s'[%d]\n",
00404                         attr.obj_nm, attr.access_nm, i );
00405                      printf( "valid range: %d - %d\nread value: %d\n",
00406                         attr.data.i16[0], attr.data.i16[1], value->i16[i] );
00407                      fmt_status = fmt_status | 2;
00408                      }
00409                   }
00410                break;
00411             case DFNT_INT32:
00412                for( i = 0; i < attr.count; i++ )
00413                   {
00414                   if( value->i32[i] < attr.data.i32[0]   ||
00415                       value->i32[i] > attr.data.i32[1]      )
00416                      {
00417                      printf( 
00418                      "**** object: '%s', outside range in attribute '%s'[%d]\n",
00419                         attr.obj_nm, attr.access_nm, i );
00420                      printf( "valid range: %d - %d\nread value: %d\n",
00421                         attr.data.i32[0], attr.data.i32[1], value->i32[i] );
00422                      fmt_status = fmt_status | 2;
00423                      }
00424                   }
00425                break;
00426             default:
00427                printf( "************* DEFAULT CASE OF VALUE CHECKING\n" );
00428                printf( "Program error\n" );
00429                fmt_status = fmt_status | 1;
00430                break;
00431             }
00432          }
00433       }
00434    return 0;
00435    }