LCOV - code coverage report
Current view: directory - frmts/grib/degrib18/degrib - degrib1.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 761 301 39.6 %
Date: 2010-01-09 Functions: 12 10 83.3 %

       1                 : /*****************************************************************************
       2                 :  * degrib1.c
       3                 :  *
       4                 :  * DESCRIPTION
       5                 :  *    This file contains the main driver routines to unpack GRIB 1 files.
       6                 :  *
       7                 :  * HISTORY
       8                 :  *   4/2003 Arthur Taylor (MDL / RSIS): Created.
       9                 :  *
      10                 :  * NOTES
      11                 :  *   GRIB 1 files are assumed to be big endian.
      12                 :  *****************************************************************************
      13                 :  */
      14                 : 
      15                 : #include <stdio.h>
      16                 : #include <string.h>
      17                 : #include <stdlib.h>
      18                 : #include <math.h>
      19                 : #include "degrib2.h"
      20                 : #include "myerror.h"
      21                 : #include "myassert.h"
      22                 : #include "memendian.h"
      23                 : #include "scan.h"
      24                 : #include "degrib1.h"
      25                 : #include "metaname.h"
      26                 : #include "clock.h"
      27                 : #include "cpl_error.h"
      28                 : 
      29                 : /* default missing data value (see: bitmap GRIB1: sect3 and sect4) */
      30                 : /* UNDEFINED is default, UNDEFINED_PRIM is desired choice. */
      31                 : #define UNDEFINED 9.999e20
      32                 : #define UNDEFINED_PRIM 9999
      33                 : 
      34                 : #define GRIB_UNSIGN_INT3(a,b,c) ((a<<16)+(b<<8)+c)
      35                 : #define GRIB_UNSIGN_INT2(a,b) ((a<<8)+b)
      36                 : #define GRIB_SIGN_INT3(a,b,c) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 127) << 16)+(b<<8)+c))
      37                 : #define GRIB_SIGN_INT2(a,b) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 0x7f) << 8) + b))
      38                 : 
      39                 : /* various centers */
      40                 : #define NMC 7
      41                 : #define US_OTHER 9
      42                 : #define CPTEC 46
      43                 : /* Canada Center */
      44                 : #define CMC 54
      45                 : #define AFWA 57
      46                 : #define DWD 78
      47                 : #define ECMWF 98
      48                 : #define ATHENS 96
      49                 : 
      50                 : /* various subcenters */
      51                 : #define SUBCENTER_MDL 14
      52                 : #define SUBCENTER_TDL 11
      53                 : 
      54                 : /* The idea of rean or opn is to give a warning about default choice of
      55                 :    which table to use. */
      56                 : #define DEF_NCEP_TABLE rean_nowarn
      57                 : enum Def_NCEP_Table { rean, opn, rean_nowarn, opn_nowarn };
      58                 : 
      59                 : extern GRIB1ParmTable parm_table_ncep_opn[256];
      60                 : extern GRIB1ParmTable parm_table_ncep_reanal[256];
      61                 : extern GRIB1ParmTable parm_table_ncep_tdl[256];
      62                 : extern GRIB1ParmTable parm_table_ncep_mdl[256];
      63                 : extern GRIB1ParmTable parm_table_omb[256];
      64                 : extern GRIB1ParmTable parm_table_nceptab_129[256];
      65                 : extern GRIB1ParmTable parm_table_nceptab_130[256];
      66                 : extern GRIB1ParmTable parm_table_nceptab_131[256];
      67                 : 
      68                 : extern GRIB1ParmTable parm_table_nohrsc[256];
      69                 : 
      70                 : extern GRIB1ParmTable parm_table_cptec_254[256];
      71                 : 
      72                 : extern GRIB1ParmTable parm_table_afwa_000[256];
      73                 : extern GRIB1ParmTable parm_table_afwa_001[256];
      74                 : extern GRIB1ParmTable parm_table_afwa_002[256];
      75                 : extern GRIB1ParmTable parm_table_afwa_003[256];
      76                 : extern GRIB1ParmTable parm_table_afwa_010[256];
      77                 : extern GRIB1ParmTable parm_table_afwa_011[256];
      78                 : 
      79                 : extern GRIB1ParmTable parm_table_dwd_002[256];
      80                 : extern GRIB1ParmTable parm_table_dwd_201[256];
      81                 : extern GRIB1ParmTable parm_table_dwd_202[256];
      82                 : extern GRIB1ParmTable parm_table_dwd_203[256];
      83                 : 
      84                 : extern GRIB1ParmTable parm_table_ecmwf_128[256];
      85                 : extern GRIB1ParmTable parm_table_ecmwf_129[256];
      86                 : extern GRIB1ParmTable parm_table_ecmwf_130[256];
      87                 : extern GRIB1ParmTable parm_table_ecmwf_131[256];
      88                 : extern GRIB1ParmTable parm_table_ecmwf_140[256];
      89                 : extern GRIB1ParmTable parm_table_ecmwf_150[256];
      90                 : extern GRIB1ParmTable parm_table_ecmwf_160[256];
      91                 : extern GRIB1ParmTable parm_table_ecmwf_170[256];
      92                 : extern GRIB1ParmTable parm_table_ecmwf_180[256];
      93                 : 
      94                 : extern GRIB1ParmTable parm_table_athens[256];
      95                 : 
      96                 : extern GRIB1ParmTable parm_table_cmc[256];
      97                 : 
      98                 : extern GRIB1ParmTable parm_table_undefined[256];
      99                 : 
     100                 : /*****************************************************************************
     101                 :  * Choose_ParmTable() --
     102                 :  *
     103                 :  * Arthur Taylor / MDL
     104                 :  *
     105                 :  * PURPOSE
     106                 :  *   Chooses the correct Parameter table depending on what is in the GRIB1
     107                 :  * message's "Product Definition Section".
     108                 :  *
     109                 :  * ARGUMENTS
     110                 :  *   pdsMeta = The filled out pdsMeta data structure to base choice on. (Input)
     111                 :  *    center = The Center that created the data (Input)
     112                 :  * subcenter = The Sub Center that created the data (Input)
     113                 :  *
     114                 :  * FILES/DATABASES: None
     115                 :  *
     116                 :  * RETURNS: ParmTable (appropriate parameter table.)
     117                 :  *
     118                 :  * HISTORY
     119                 :  *   <unknown> : wgrib library : cnames.c
     120                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Modified
     121                 :  *  10/2005 AAT: Adjusted to take center, subcenter
     122                 :  *
     123                 :  * NOTES
     124                 :  *****************************************************************************
     125                 :  */
     126              20 : static GRIB1ParmTable *Choose_ParmTable (pdsG1Type *pdsMeta,
     127                 :                                          unsigned short int center,
     128                 :                                          unsigned short int subcenter)
     129                 : {
     130                 :    int process;         /* The process ID from the GRIB1 message. */
     131                 : 
     132              20 :    switch (center) {
     133                 :       case NMC:
     134              20 :          if (pdsMeta->mstrVersion <= 3) {
     135              16 :             switch (subcenter) {
     136                 :                case 1:
     137               0 :                   return &parm_table_ncep_reanal[0];
     138                 :                case SUBCENTER_TDL:
     139               0 :                   return &parm_table_ncep_tdl[0];
     140                 :                case SUBCENTER_MDL:
     141               0 :                   return &parm_table_ncep_mdl[0];
     142                 :             }
     143                 :          }
     144                 :          /* figure out if NCEP opn or reanalysis */
     145              20 :          switch (pdsMeta->mstrVersion) {
     146                 :             case 0:
     147              10 :                return &parm_table_ncep_opn[0];
     148                 :             case 1:
     149                 :             case 2:
     150               6 :                process = pdsMeta->genProcess;
     151               6 :                if ((subcenter != 0) || ((process != 80) && (process != 180))) {
     152               6 :                   return &parm_table_ncep_opn[0];
     153                 :                }
     154                 :                /* At this point could be either the opn or reanalysis table */
     155                 :                switch (DEF_NCEP_TABLE) {
     156                 :                   case opn_nowarn:
     157                 :                      return &parm_table_ncep_opn[0];
     158                 :                   case rean_nowarn:
     159               0 :                      return &parm_table_ncep_reanal[0];
     160                 :                }
     161                 :                break;
     162                 :             case 3:
     163               0 :                return &parm_table_ncep_opn[0];
     164                 :             case 128:
     165               0 :                return &parm_table_omb[0];
     166                 :             case 129:
     167               4 :                return &parm_table_nceptab_129[0];
     168                 :             case 130:
     169               0 :                return &parm_table_nceptab_130[0];
     170                 :             case 131:
     171               0 :                return &parm_table_nceptab_131[0];
     172                 :          }
     173               0 :          break;
     174                 :       case AFWA:
     175               0 :          switch (subcenter) {
     176                 :             case 0:
     177               0 :                return &parm_table_afwa_000[0];
     178                 :             case 1:
     179                 :             case 4:
     180               0 :                return &parm_table_afwa_001[0];
     181                 :             case 2:
     182               0 :                return &parm_table_afwa_002[0];
     183                 :             case 3:
     184               0 :                return &parm_table_afwa_003[0];
     185                 :             case 10:
     186               0 :                return &parm_table_afwa_010[0];
     187                 :             case 11:
     188               0 :                return &parm_table_afwa_011[0];
     189                 : /*            case 5:*/
     190                 :                /* Didn't have a table 5. */
     191                 :          }
     192               0 :          break;
     193                 :       case ECMWF:
     194               0 :          switch (pdsMeta->mstrVersion) {
     195                 :             case 128:
     196               0 :                return &parm_table_ecmwf_128[0];
     197                 :             case 129:
     198               0 :                return &parm_table_ecmwf_129[0];
     199                 :             case 130:
     200               0 :                return &parm_table_ecmwf_130[0];
     201                 :             case 131:
     202               0 :                return &parm_table_ecmwf_131[0];
     203                 :             case 140:
     204               0 :                return &parm_table_ecmwf_140[0];
     205                 :             case 150:
     206               0 :                return &parm_table_ecmwf_150[0];
     207                 :             case 160:
     208               0 :                return &parm_table_ecmwf_160[0];
     209                 :             case 170:
     210               0 :                return &parm_table_ecmwf_170[0];
     211                 :             case 180:
     212               0 :                return &parm_table_ecmwf_180[0];
     213                 :          }
     214               0 :          break;
     215                 :       case DWD:
     216               0 :          switch (pdsMeta->mstrVersion) {
     217                 :             case 2:
     218               0 :                return &parm_table_dwd_002[0];
     219                 :             case 201:
     220               0 :                return &parm_table_dwd_201[0];
     221                 :             case 202:
     222               0 :                return &parm_table_dwd_202[0];
     223                 :             case 203:
     224               0 :                return &parm_table_dwd_203[0];
     225                 :          }
     226               0 :          break;
     227                 :       case CPTEC:
     228               0 :          switch (pdsMeta->mstrVersion) {
     229                 :             case 254:
     230               0 :                return &parm_table_cptec_254[0];
     231                 :          }
     232               0 :          break;
     233                 :       case US_OTHER:
     234               0 :          switch (subcenter) {
     235                 :             case 163:
     236               0 :                return &parm_table_nohrsc[0];
     237                 :          }
     238               0 :          break;
     239                 :       case ATHENS:
     240               0 :          return &parm_table_athens[0];
     241                 :          break;
     242                 :       case CMC:
     243               0 :          return &parm_table_cmc[0];
     244                 :          break;
     245                 :    }
     246               0 :    if ((pdsMeta->mstrVersion > 3) || (pdsMeta->cat > 127)) {
     247                 :        CPLDebug (
     248                 :            "GRIB",
     249                 :            "Undefined parameter table (center %d-%d table %d).",
     250               0 :            center, subcenter, pdsMeta->mstrVersion);
     251                 :    }
     252               0 :    return &parm_table_undefined[0];
     253                 : }
     254                 : 
     255                 : /*****************************************************************************
     256                 :  * GRIB1_Table2LookUp() --
     257                 :  *
     258                 :  * Arthur Taylor / MDL
     259                 :  *
     260                 :  * PURPOSE
     261                 :  *   Returns the variable name (type of data) and comment (longer form of the
     262                 :  * name) for the data that is in the GRIB1 message.
     263                 :  *
     264                 :  * ARGUMENTS
     265                 :  *      name = A pointer to the resulting short name. (Output)
     266                 :  *   comment = A pointer to the resulting long name. (Output)
     267                 :  *   pdsMeta = The filled out pdsMeta data structure to base choice on. (Input)
     268                 :  *    center = The Center that created the data (Input)
     269                 :  * subcenter = The Sub Center that created the data (Input)
     270                 :  *
     271                 :  * FILES/DATABASES: None
     272                 :  *
     273                 :  * RETURNS: void
     274                 :  *
     275                 :  * HISTORY
     276                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
     277                 :  *  10/2005 AAT: Adjusted to take center, subcenter
     278                 :  *
     279                 :  * NOTES
     280                 :  *****************************************************************************
     281                 :  */
     282              20 : static void GRIB1_Table2LookUp (pdsG1Type *pdsMeta, const char **name,
     283                 :                                 const char **comment, const char **unit,
     284                 :                                 int *convert,
     285                 :                                 unsigned short int center,
     286                 :                                 unsigned short int subcenter)
     287                 : {
     288                 :    GRIB1ParmTable *table; /* The paramter table choosen by the pdsMeta data */
     289                 : 
     290              20 :    table = Choose_ParmTable (pdsMeta, center, subcenter);
     291              20 :    if ((center == NMC) && (pdsMeta->mstrVersion == 129)
     292                 :        && (pdsMeta->cat == 180)) {
     293               0 :       if (pdsMeta->timeRange == 3) {
     294               0 :          *name = "AVGOZCON";
     295               0 :          *comment = "Average Ozone Concentration";
     296               0 :          *unit = "PPB";
     297               0 :          *convert = UC_NONE;
     298               0 :          return;
     299                 :       }
     300                 :    }
     301              20 :    *name = table[pdsMeta->cat].name;
     302              20 :    *comment = table[pdsMeta->cat].comment;
     303              20 :    *unit = table[pdsMeta->cat].unit;
     304              20 :    *convert = table[pdsMeta->cat].convert;
     305                 : /*   printf ("%s %s %s\n", *name, *comment, *unit);*/
     306                 : }
     307                 : 
     308                 : extern GRIB1SurfTable GRIB1Surface[256];
     309                 : 
     310                 : /* Similar to metaname.c :: ParseLevelName() */
     311              20 : static void GRIB1_Table3LookUp (pdsG1Type *pdsMeta, char **shortLevelName,
     312                 :                                 char **longLevelName)
     313                 : {
     314              20 :    uChar type = pdsMeta->levelType;
     315                 :    uChar level1, level2;
     316                 : 
     317              20 :    free (*shortLevelName);
     318              20 :    *shortLevelName = NULL;
     319              20 :    free (*longLevelName);
     320              20 :    *longLevelName = NULL;
     321                 :    /* Find out if val is a 2 part value or not */
     322              20 :    if (GRIB1Surface[type].f_twoPart) {
     323               0 :       level1 = (pdsMeta->levelVal >> 8);
     324               0 :       level2 = (pdsMeta->levelVal & 0xff);
     325                 :       reallocSprintf (shortLevelName, "%d-%d-%s", level1, level2,
     326               0 :                       GRIB1Surface[type].name);
     327                 :       reallocSprintf (longLevelName, "%d-%d[%s] %s (%s)", level1, level2,
     328                 :                       GRIB1Surface[type].unit, GRIB1Surface[type].name,
     329               0 :                       GRIB1Surface[type].comment);
     330                 :    } else {
     331                 :       reallocSprintf (shortLevelName, "%d-%s", pdsMeta->levelVal,
     332              20 :                       GRIB1Surface[type].name);
     333                 :       reallocSprintf (longLevelName, "%d[%s] %s (%s)", pdsMeta->levelVal,
     334                 :                       GRIB1Surface[type].unit, GRIB1Surface[type].name,
     335              20 :                       GRIB1Surface[type].comment);
     336                 :    }
     337              20 : }
     338                 : 
     339                 : /*****************************************************************************
     340                 :  * fval_360() --
     341                 :  *
     342                 :  * Albion Taylor / ARL
     343                 :  *
     344                 :  * PURPOSE
     345                 :  *   Converts an IBM360 floating point number to an IEEE floating point
     346                 :  * number.  The IBM floating point spec represents the fraction as the last
     347                 :  * 3 bytes of the number, with 0xffffff being just shy of 1.0.  The first byte
     348                 :  * leads with a sign bit, and the last seven bits represent the powers of 16
     349                 :  * (not 2), with a bias of 0x40 giving 16^0.
     350                 :  *
     351                 :  * ARGUMENTS
     352                 :  * aval = A sInt4 containing the original IBM 360 number. (Input)
     353                 :  *
     354                 :  * FILES/DATABASES: None
     355                 :  *
     356                 :  * RETURNS: double = the value that aval represents.
     357                 :  *
     358                 :  * HISTORY
     359                 :  *   <unknown> Albion Taylor (ARL): Created
     360                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Cleaned up.
     361                 :  *   5/2003 AAT: some kind of Bug due to optimizations...
     362                 :  *          -1055916032 => 0 instead of -1
     363                 :  *
     364                 :  * NOTES
     365                 :  *****************************************************************************
     366                 :  */
     367               4 : static double fval_360 (uInt4 aval)
     368                 : {
     369                 :    double pow16;
     370                 : /*   short int *ptr = (short int *) (&pow16);*/
     371               4 :    void *voidPtr = &pow16;
     372               4 :    short int *ptr = (short int *) voidPtr;
     373                 : 
     374                 : #ifdef LITTLE_ENDIAN
     375               4 :    ptr[3] = ((((aval >> 24) & 0x7f) << 2) + (0x3ff - 0x100)) << 4;
     376               4 :    ptr[2] = 0;
     377               4 :    ptr[1] = 0;
     378               4 :    ptr[0] = 0;
     379                 : #else
     380                 :    ptr[0] = ((((aval >> 24) & 0x7f) << 2) + (0x3ff - 0x100)) << 4;
     381                 :    ptr[1] = 0;
     382                 :    ptr[2] = 0;
     383                 :    ptr[3] = 0;
     384                 : #endif
     385                 :    return ((aval & 0x80000000) ? -pow16 : pow16) *
     386               4 :          (aval & 0xffffff) / ((double) 0x1000000);
     387                 : }
     388                 : 
     389                 : /*****************************************************************************
     390                 :  * ReadGrib1Sect1() --
     391                 :  *
     392                 :  * Arthur Taylor / MDL
     393                 :  *
     394                 :  * PURPOSE
     395                 :  *   Parses the GRIB1 "Product Definition Section" or section 1, filling out
     396                 :  * the pdsMeta data structure.
     397                 :  *
     398                 :  * ARGUMENTS
     399                 :  *       pds = The compressed part of the message dealing with "PDS". (Input)
     400                 :  *   gribLen = The total length of the GRIB1 message. (Input)
     401                 :  *    curLoc = Current location in the GRIB1 message. (Output)
     402                 :  *   pdsMeta = The filled out pdsMeta data structure. (Output)
     403                 :  *     f_gds = boolean if there is a Grid Definition Section. (Output)
     404                 :  *    gridID = The Grid ID. (Output)
     405                 :  *     f_bms = boolean if there is a Bitmap Section. (Output)
     406                 :  *       DSF = Decimal Scale Factor for unpacking the data. (Output)
     407                 :  *    center = The Center that created the data (Output)
     408                 :  * subcenter = The Sub Center that created the data (Output)
     409                 :  *
     410                 :  * FILES/DATABASES: None
     411                 :  *
     412                 :  * RETURNS: int (could use errSprintf())
     413                 :  *  0 = OK
     414                 :  * -1 = gribLen is too small.
     415                 :  *
     416                 :  * HISTORY
     417                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created.
     418                 :  *   5/2004 AAT: Paid attention to table 5 (Time range indicator) and which of
     419                 :  *          P1 and P2 are the valid times.
     420                 :  *  10/2005 AAT: Adjusted to take center, subcenter
     421                 :  *
     422                 :  * NOTES
     423                 :  *****************************************************************************
     424                 :  */
     425              20 : static int ReadGrib1Sect1 (uChar *pds, uInt4 gribLen, uInt4 *curLoc,
     426                 :                            pdsG1Type *pdsMeta, char *f_gds, uChar *gridID,
     427                 :                            char *f_bms, short int *DSF,
     428                 :                            unsigned short int *center,
     429                 :                            unsigned short int *subcenter)
     430                 : {
     431                 :    sInt4 sectLen;       /* Length in bytes of the current section. */
     432                 :    int year;            /* The year of the GRIB1 Message. */
     433                 :    double P1_DeltaTime; /* Used to parse the time for P1 */
     434                 :    double P2_DeltaTime; /* Used to parse the time for P2 */
     435                 :    uInt4 uli_temp;
     436                 : #ifdef DEBUG
     437                 : /*
     438                 :    int i;
     439                 : */
     440                 : #endif
     441                 : 
     442              20 :    sectLen = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
     443                 : #ifdef DEBUG
     444                 : /*
     445                 :    printf ("Section 1 length = %ld\n", sectLen);
     446                 :    for (i = 0; i < sectLen; i++) {
     447                 :       printf ("Sect1: item %d = %d\n", i + 1, pds[i]);
     448                 :    }
     449                 :    printf ("Century is item 25\n");
     450                 : */
     451                 : #endif
     452              20 :    *curLoc += sectLen;
     453              20 :    if (*curLoc > gribLen) {
     454               0 :       errSprintf ("Ran out of data in PDS (GRIB 1 Section 1)\n");
     455               0 :       return -1;
     456                 :    }
     457              20 :    pds += 3;
     458              20 :    pdsMeta->mstrVersion = *(pds++);
     459              20 :    *center = *(pds++);
     460              20 :    pdsMeta->genProcess = *(pds++);
     461              20 :    *gridID = *(pds++);
     462              20 :    *f_gds = GRIB2BIT_1 & *pds;
     463              20 :    *f_bms = GRIB2BIT_2 & *pds;
     464              20 :    pds++;
     465              20 :    pdsMeta->cat = *(pds++);
     466              20 :    pdsMeta->levelType = *(pds++);
     467              20 :    pdsMeta->levelVal = GRIB_UNSIGN_INT2 (*pds, pds[1]);
     468              20 :    pds += 2;
     469              20 :    if (*pds == 0) {
     470                 :       /* The 12 is because we have increased pds by 12. (but 25 is in
     471                 :        * reference of 1..25, so we need another -1) */
     472               0 :       year = (pds[25 - 13] * 100);
     473                 :    } else {
     474                 :       /* The 12 is because we have increased pds by 12. (but 25 is in
     475                 :        * reference of 1..25, so we need another -1) */
     476              20 :       year = *pds + ((pds[25 - 13] - 1) * 100);
     477                 : 
     478                 :       /* It seems like some old files (such as spring/I000176.grb)
     479                 :          do not have a century byte, and assum 19xx. */
     480                 : //      if( (year < 1900 || year > 2100) && *pds >= 0 && *pds < 100 )
     481                 : //          year = *pds + 1900;
     482                 :    }
     483                 : 
     484              20 :    if (ParseTime (&(pdsMeta->refTime), year, pds[1], pds[2], pds[3], pds[4],
     485                 :                   0) != 0) {
     486               0 :       preErrSprintf ("Error In call to ParseTime\n");
     487               0 :       errSprintf ("(Probably a corrupt file)\n");
     488               0 :       return -1;
     489                 :    }
     490              20 :    pds += 5;
     491              20 :    pdsMeta->timeRange = pds[3];
     492              20 :    if (ParseSect4Time2secV1 (pds[1], *pds, &P1_DeltaTime) == 0) {
     493              20 :       pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
     494                 :    } else {
     495               0 :       pdsMeta->P1 = pdsMeta->refTime;
     496               0 :       printf ("Warning! : Can't figure out time unit of %d\n", *pds);
     497                 :    }
     498              20 :    if (ParseSect4Time2secV1 (pds[2], *pds, &P2_DeltaTime) == 0) {
     499              20 :       pdsMeta->P2 = pdsMeta->refTime + P2_DeltaTime;
     500                 :    } else {
     501               0 :       pdsMeta->P2 = pdsMeta->refTime;
     502               0 :       printf ("Warning! : Can't figure out time unit of %d\n", *pds);
     503                 :    }
     504                 :    /* The following is based on Table 5. */
     505                 :    /* Note: For ensemble forecasts, 119 has meaning. */
     506              20 :    switch (pdsMeta->timeRange) {
     507                 :       case 0:
     508                 :       case 1:
     509                 :       case 113:
     510                 :       case 114:
     511                 :       case 115:
     512                 :       case 116:
     513                 :       case 117:
     514                 :       case 118:
     515                 :       case 123:
     516                 :       case 124:
     517              16 :          pdsMeta->validTime = pdsMeta->P1;
     518              16 :          break;
     519                 :       case 2:
     520                 :          /* Puzzling case. */
     521               0 :          pdsMeta->validTime = pdsMeta->P2;
     522               0 :          break;
     523                 :       case 3:
     524                 :       case 4:
     525                 :       case 5:
     526                 :       case 51:
     527               0 :          pdsMeta->validTime = pdsMeta->P2;
     528               0 :          break;
     529                 :       case 10:
     530               4 :          if (ParseSect4Time2secV1 (GRIB_UNSIGN_INT2 (pds[1], pds[2]), *pds,
     531                 :                                    &P1_DeltaTime) == 0) {
     532               4 :             pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
     533                 :          } else {
     534               0 :             pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime;
     535               0 :             printf ("Warning! : Can't figure out time unit of %d\n", *pds);
     536                 :          }
     537               4 :          pdsMeta->validTime = pdsMeta->P1;
     538               4 :          break;
     539                 :       default:
     540               0 :          pdsMeta->validTime = pdsMeta->P1;
     541                 :    }
     542              20 :    pds += 4;
     543              20 :    pdsMeta->Average = GRIB_UNSIGN_INT2 (*pds, pds[1]);
     544              20 :    pds += 2;
     545              20 :    pdsMeta->numberMissing = *(pds++);
     546                 :    /* Skip over centry of reference time. */
     547              20 :    pds++;
     548              20 :    *subcenter = *(pds++);
     549              20 :    *DSF = GRIB_SIGN_INT2 (*pds, pds[1]);
     550              20 :    pds += 2;
     551              20 :    pdsMeta->f_hasEns = 0;
     552              20 :    pdsMeta->f_hasProb = 0;
     553              20 :    pdsMeta->f_hasCluster = 0;
     554              20 :    if (sectLen < 41) {
     555              20 :       return 0;
     556                 :    }
     557                 :    /* Following is based on:
     558                 :     * http://www.emc.ncep.noaa.gov/gmb/ens/info/ens_grib.html */
     559               0 :    if ((*center == NMC) && (*subcenter == 2)) {
     560               0 :       if (sectLen < 45) {
     561               0 :          printf ("Warning! Problems with Ensemble section\n");
     562               0 :          return 0;
     563                 :       }
     564               0 :       pdsMeta->f_hasEns = 1;
     565               0 :       pdsMeta->ens.BitFlag = *(pds++);
     566                 : /*      octet21 = pdsMeta->timeRange; = 119 has meaning now */
     567               0 :       pds += 11;
     568               0 :       pdsMeta->ens.Application = *(pds++);
     569               0 :       pdsMeta->ens.Type = *(pds++);
     570               0 :       pdsMeta->ens.Number = *(pds++);
     571               0 :       pdsMeta->ens.ProdID = *(pds++);
     572               0 :       pdsMeta->ens.Smooth = *(pds++);
     573               0 :       if ((pdsMeta->cat == 191) || (pdsMeta->cat == 192) ||
     574                 :           (pdsMeta->cat == 193)) {
     575               0 :          if (sectLen < 60) {
     576               0 :             printf ("Warning! Problems with Ensemble Probability section\n");
     577               0 :             return 0;
     578                 :          }
     579               0 :          pdsMeta->f_hasProb = 1;
     580               0 :          pdsMeta->prob.Cat = pdsMeta->cat;
     581               0 :          pdsMeta->cat = *(pds++);
     582               0 :          pdsMeta->prob.Type = *(pds++);
     583               0 :          MEMCPY_BIG (&uli_temp, pds, sizeof (sInt4));
     584               0 :          pdsMeta->prob.lower = fval_360 (uli_temp);
     585               0 :          pds += 4;
     586               0 :          MEMCPY_BIG (&uli_temp, pds, sizeof (sInt4));
     587               0 :          pdsMeta->prob.upper = fval_360 (uli_temp);
     588               0 :          pds += 4;
     589               0 :          pds += 4;
     590                 :       }
     591               0 :       if ((pdsMeta->ens.Type == 4) || (pdsMeta->ens.Type == 5)) {
     592                 :          /* 87 ... 100 was reserved, but may not be encoded */
     593               0 :          if ((sectLen < 100) && (sectLen != 86)) {
     594               0 :             printf ("Warning! Problems with Ensemble Clustering section\n");
     595               0 :             printf ("Section length == %d\n", sectLen);
     596               0 :             return 0;
     597                 :          }
     598               0 :          if (pdsMeta->f_hasProb == 0) {
     599               0 :             pds += 14;
     600                 :          }
     601               0 :          pdsMeta->f_hasCluster = 1;
     602               0 :          pdsMeta->cluster.ensSize = *(pds++);
     603               0 :          pdsMeta->cluster.clusterSize = *(pds++);
     604               0 :          pdsMeta->cluster.Num = *(pds++);
     605               0 :          pdsMeta->cluster.Method = *(pds++);
     606               0 :          pdsMeta->cluster.NorLat = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
     607               0 :          pdsMeta->cluster.NorLat = pdsMeta->cluster.NorLat / 1000.;
     608               0 :          pds += 3;
     609               0 :          pdsMeta->cluster.SouLat = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
     610               0 :          pdsMeta->cluster.SouLat = pdsMeta->cluster.SouLat / 1000.;
     611               0 :          pds += 3;
     612               0 :          pdsMeta->cluster.EasLon = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
     613               0 :          pdsMeta->cluster.EasLon = pdsMeta->cluster.EasLon / 1000.;
     614               0 :          pds += 3;
     615               0 :          pdsMeta->cluster.WesLon = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
     616               0 :          pdsMeta->cluster.WesLon = pdsMeta->cluster.WesLon / 1000.;
     617               0 :          pds += 3;
     618               0 :          memcpy (pdsMeta->cluster.Member, pds, 10);
     619               0 :          pdsMeta->cluster.Member[10] = '\0';
     620                 :       }
     621                 :       /* Following based on:
     622                 :        * http://www.ecmwf.int/publications/manuals/libraries/gribex/
     623                 :        * localGRIBUsage.html */
     624               0 :    } else if (*center == ECMWF) {
     625               0 :       if (sectLen < 45) {
     626               0 :          printf ("Warning! Problems with ECMWF PDS extension\n");
     627               0 :          return 0;
     628                 :       }
     629                 :       /*
     630                 :       sInt4 i_temp;
     631                 :       pds += 12;
     632                 :       i_temp = GRIB_SIGN_INT2 (pds[3], pds[4]);
     633                 :       printf ("ID %d Class %d Type %d Stream %d", pds[0], pds[1], pds[2],
     634                 :               i_temp);
     635                 :       pds += 5;
     636                 :       printf (" Ver %c%c%c%c, ", pds[0], pds[1], pds[2], pds[3]);
     637                 :       pds += 4;
     638                 :       printf ("Octet-50 %d, Octet-51 %d SectLen %d\n", pds[0], pds[1],
     639                 :               sectLen);
     640                 :       */
     641                 :    } else {
     642                 :       printf ("Un-handled possible ensemble section center %d "
     643               0 :               "subcenter %d\n", *center, *subcenter);
     644                 :    }
     645               0 :    return 0;
     646                 : }
     647                 : 
     648                 : /*****************************************************************************
     649                 :  * Grib1_Inventory() --
     650                 :  *
     651                 :  * Arthur Taylor / MDL
     652                 :  *
     653                 :  * PURPOSE
     654                 :  *   Parses the GRIB1 "Product Definition Section" for enough information to
     655                 :  * fill out the inventory data structure so we can do a simple inventory on
     656                 :  * the file in a similar way to how we did it for GRIB2.
     657                 :  *
     658                 :  * ARGUMENTS
     659                 :  *      fp = An opened GRIB2 file already at the correct message. (Input)
     660                 :  * gribLen = The total length of the GRIB1 message. (Input)
     661                 :  *     inv = The inventory data structure that we need to fill. (Output)
     662                 :  *
     663                 :  * FILES/DATABASES: None
     664                 :  *
     665                 :  * RETURNS: int (could use errSprintf())
     666                 :  *  0 = OK
     667                 :  * -1 = gribLen is too small.
     668                 :  *
     669                 :  * HISTORY
     670                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created.
     671                 :  *
     672                 :  * NOTES
     673                 :  *****************************************************************************
     674                 :  */
     675              16 : int GRIB1_Inventory (DataSource &fp, uInt4 gribLen, inventoryType *inv)
     676                 : {
     677                 :    char temp[3];        /* Used to determine the section length. */
     678                 :    uInt4 sectLen;       /* Length in bytes of the current section. */
     679                 :    uChar *pds;          /* The part of the message dealing with the PDS. */
     680                 :    pdsG1Type pdsMeta;   /* The pds parsed into a usable data structure. */
     681                 :    char f_gds;          /* flag if there is a gds section. */
     682                 :    char f_bms;          /* flag if there is a bms section. */
     683                 :    short int DSF;       /* Decimal Scale Factor for unpacking the data. */
     684                 :    uChar gridID;        /* Which GDS specs to use. */
     685                 :    const char *varName; /* The name of the data stored in the grid. */
     686                 :    const char *varComment; /* Extra comments about the data stored in grid. */
     687                 :    const char *varUnit; /* Holds the name of the unit [K] [%] .. etc */
     688                 :    int convert;         /* Conversion method for this variable's unit. */
     689                 :    uInt4 curLoc;        /* Where we are in the current GRIB message. */
     690                 :    unsigned short int center; /* The Center that created the data */
     691                 :    unsigned short int subcenter; /* The Sub Center that created the data */
     692                 : 
     693              16 :    curLoc = 8;
     694              16 :    if (fp.DataSourceFread(temp, sizeof (char), 3) != 3) {
     695               0 :       errSprintf ("Ran out of file.\n");
     696               0 :       return -1;
     697                 :    }
     698              16 :    sectLen = GRIB_UNSIGN_INT3 (*temp, temp[1], temp[2]);
     699              16 :    if (curLoc + sectLen > gribLen) {
     700               0 :       errSprintf ("Ran out of data in PDS (GRIB1_Inventory)\n");
     701               0 :       return -1;
     702                 :    }
     703              16 :    pds = (uChar *) malloc (sectLen * sizeof (uChar));
     704              16 :    *pds = *temp;
     705              16 :    pds[1] = temp[1];
     706              16 :    pds[2] = temp[2];
     707              16 :    if (fp.DataSourceFread(pds + 3, sizeof (char), sectLen - 3) + 3 != sectLen) {
     708               0 :       errSprintf ("Ran out of file.\n");
     709               0 :       free (pds);
     710               0 :       return -1;
     711                 :    }
     712                 : 
     713              16 :    if (ReadGrib1Sect1 (pds, gribLen, &curLoc, &pdsMeta, &f_gds, &gridID,
     714                 :                        &f_bms, &DSF, &center, &subcenter) != 0) {
     715               0 :       preErrSprintf ("Inside GRIB1_Inventory\n");
     716               0 :       free (pds);
     717               0 :       return -1;
     718                 :    }
     719              16 :    free (pds);
     720              16 :    inv->refTime = pdsMeta.refTime;
     721              16 :    inv->validTime = pdsMeta.validTime;
     722              16 :    inv->foreSec = inv->validTime - inv->refTime;
     723                 :    GRIB1_Table2LookUp (&(pdsMeta), &varName, &varComment, &varUnit,
     724              16 :                        &convert, center, subcenter);
     725              16 :    inv->element = (char *) malloc ((1 + strlen (varName)) * sizeof (char));
     726              16 :    strcpy (inv->element, varName);
     727                 :    inv->unitName = (char *) malloc ((1 + 2 + strlen (varUnit)) *
     728              16 :                                     sizeof (char));
     729              16 :    sprintf (inv->unitName, "[%s]", varUnit);
     730                 :    inv->comment = (char *) malloc ((1 + strlen (varComment) +
     731                 :                                     strlen (varUnit) + 2 + 1) *
     732              16 :                                    sizeof (char));
     733              16 :    sprintf (inv->comment, "%s [%s]", varComment, varUnit);
     734                 : 
     735                 :    GRIB1_Table3LookUp (&(pdsMeta), &(inv->shortFstLevel),
     736              16 :                        &(inv->longFstLevel));
     737                 : 
     738                 :    /* Get to the end of the GRIB1 message. */
     739                 :    /* (inventory.c : GRIB2Inventory), is responsible for this. */
     740                 :    /* fseek (fp, gribLen - sectLen, SEEK_CUR); */
     741              16 :    return 0;
     742                 : }
     743                 : 
     744               0 : int GRIB1_RefTime (DataSource &fp, uInt4 gribLen, double *refTime)
     745                 : {
     746                 :    char temp[3];        /* Used to determine the section length. */
     747                 :    uInt4 sectLen;       /* Length in bytes of the current section. */
     748                 :    uChar *pds;          /* The part of the message dealing with the PDS. */
     749                 :    pdsG1Type pdsMeta;   /* The pds parsed into a usable data structure. */
     750                 :    char f_gds;          /* flag if there is a gds section. */
     751                 :    char f_bms;          /* flag if there is a bms section. */
     752                 :    short int DSF;       /* Decimal Scale Factor for unpacking the data. */
     753                 :    uChar gridID;        /* Which GDS specs to use. */
     754                 :    uInt4 curLoc;        /* Where we are in the current GRIB message. */
     755                 :    unsigned short int center; /* The Center that created the data */
     756                 :    unsigned short int subcenter; /* The Sub Center that created the data */
     757                 : 
     758               0 :    curLoc = 8;
     759               0 :    if (fp.DataSourceFread (temp, sizeof (char), 3) != 3) {
     760               0 :       errSprintf ("Ran out of file.\n");
     761               0 :       return -1;
     762                 :    }
     763               0 :    sectLen = GRIB_UNSIGN_INT3 (*temp, temp[1], temp[2]);
     764               0 :    if (curLoc + sectLen > gribLen) {
     765               0 :       errSprintf ("Ran out of data in PDS (GRIB1_Inventory)\n");
     766               0 :       return -1;
     767                 :    }
     768               0 :    pds = (uChar *) malloc (sectLen * sizeof (uChar));
     769               0 :    *pds = *temp;
     770               0 :    pds[1] = temp[1];
     771               0 :    pds[2] = temp[2];
     772               0 :    if (fp.DataSourceFread (pds + 3, sizeof (char), sectLen - 3) + 3 != sectLen) {
     773               0 :       errSprintf ("Ran out of file.\n");
     774               0 :       free (pds);
     775               0 :       return -1;
     776                 :    }
     777                 : 
     778               0 :    if (ReadGrib1Sect1 (pds, gribLen, &curLoc, &pdsMeta, &f_gds, &gridID,
     779                 :                        &f_bms, &DSF, &center, &subcenter) != 0) {
     780               0 :       preErrSprintf ("Inside GRIB1_Inventory\n");
     781               0 :       free (pds);
     782               0 :       return -1;
     783                 :    }
     784               0 :    free (pds);
     785                 : 
     786               0 :    *refTime = pdsMeta.refTime;
     787                 : 
     788                 :    /* Get to the end of the GRIB1 message. */
     789                 :    /* (inventory.c : GRIB2Inventory), is responsible for this. */
     790                 :    /* fseek (fp, gribLen - sectLen, SEEK_CUR); */
     791               0 :    return 0;
     792                 : }
     793                 : 
     794                 : /*****************************************************************************
     795                 :  * ReadGrib1Sect2() --
     796                 :  *
     797                 :  * Arthur Taylor / MDL
     798                 :  *
     799                 :  * PURPOSE
     800                 :  *   Parses the GRIB1 "Grid Definition Section" or section 2, filling out
     801                 :  * the gdsMeta data structure.
     802                 :  *
     803                 :  * ARGUMENTS
     804                 :  *     gds = The compressed part of the message dealing with "GDS". (Input)
     805                 :  * gribLen = The total length of the GRIB1 message. (Input)
     806                 :  *  curLoc = Current location in the GRIB1 message. (Output)
     807                 :  * gdsMeta = The filled out gdsMeta data structure. (Output)
     808                 :  *
     809                 :  * FILES/DATABASES: None
     810                 :  *
     811                 :  * RETURNS: int (could use errSprintf())
     812                 :  *  0 = OK
     813                 :  * -1 = gribLen is too small.
     814                 :  * -2 = unexpected values in gds.
     815                 :  *
     816                 :  * HISTORY
     817                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created.
     818                 :  *  12/2003 AAT: adas data encoder seems to have # of vertical data = 1, but
     819                 :  *        parameters of vertical data = 255, which doesn't make sense.
     820                 :  *        Changed the error from "fatal" to a warning in debug mode.
     821                 :  *   6/2004 AAT: Modified to allow "extended" lat/lon grids (ie stretched or
     822                 :  *        stretched and rotated).
     823                 :  *
     824                 :  * NOTES
     825                 :  *****************************************************************************
     826                 :  */
     827               4 : static int ReadGrib1Sect2 (uChar *gds, uInt4 gribLen, uInt4 *curLoc,
     828                 :                            gdsType *gdsMeta)
     829                 : {
     830                 :    uInt4 sectLen;       /* Length in bytes of the current section. */
     831                 :    int gridType;        /* Which type of grid. (see enumerated types). */
     832               4 :    double unit = 1e-3; /* Used for converting to the correct unit. */
     833                 :    uInt4 uli_temp;      /* Used for reading a GRIB1 float. */
     834                 :    int i;
     835                 :    int f_allZero;       /* Used to find out if the "lat/lon" extension part
     836                 :                          * is all 0 hence missing. */
     837                 :    int f_allOne;        /* Used to find out if the "lat/lon" extension part
     838                 :                          * is all 1 hence missing. */
     839                 : 
     840               4 :    sectLen = GRIB_UNSIGN_INT3 (*gds, gds[1], gds[2]);
     841                 : #ifdef DEBUG
     842                 : /*
     843                 :    printf ("Section 2 length = %ld\n", sectLen);
     844                 : */
     845                 : #endif
     846               4 :    *curLoc += sectLen;
     847               4 :    if (*curLoc > gribLen) {
     848               0 :       errSprintf ("Ran out of data in GDS (GRIB 1 Section 2)\n");
     849               0 :       return -1;
     850                 :    }
     851               4 :    gds += 3;
     852                 : /*
     853                 : #ifdef DEBUG
     854                 :    if ((*gds != 0) || (gds[1] != 255)) {
     855                 :       printf ("GRIB1 GDS: Expect (NV = 0) != %d, (PV = 255) != %d\n",
     856                 :               *gds, gds[1]);
     857                 :       errSprintf ("SectLen == %ld\n", sectLen);
     858                 :       errSprintf ("GridType == %d\n", gds[2]);
     859                 :    }
     860                 : #endif
     861                 : */
     862                 : #ifdef DEBUG
     863                 :    if (gds[1] != 255) {
     864                 :       printf ("\n\tCaution: GRIB1 GDS: FOR ALL NWS products, PV should be "
     865                 :               "255 rather than %d\n", gds[1]);
     866                 :    }
     867                 : #endif
     868               4 :    if ((gds[1] != 255) && (gds[1] > 6)) {
     869               0 :       errSprintf ("GRIB1 GDS: Expect PV = 255 != %d\n", gds[1]);
     870               0 :       return -2;
     871                 :    }
     872               4 :    gds += 2;
     873               4 :    gridType = *(gds++);
     874               4 :    switch (gridType) {
     875                 :       case GB1S2_LATLON: // Latitude/Longitude Grid
     876                 :       case GB1S2_GAUSSIAN_LATLON: // Gaussian Latitude/Longitude
     877                 :       case GB1S2_ROTATED_LATLON: // Rotated Latitude/Longitude
     878               4 :          if ((sectLen != 32) && (sectLen != 42) && (sectLen != 52)) {
     879                 :             errSprintf ("For LatLon GDS, should have 32 or 42 or 52 bytes "
     880               0 :                         "of data\n");
     881               0 :             return -1;
     882                 :          }
     883               4 :          switch(gridType) {
     884                 :          case GB1S2_GAUSSIAN_LATLON:
     885               0 :             gdsMeta->projType = GS3_GAUSSIAN_LATLON;
     886               0 :             break;
     887                 :          case GB1S2_ROTATED_LATLON:
     888               0 :             gdsMeta->projType = GS3_ROTATED_LATLON;
     889               0 :             break;
     890                 :          default:
     891               4 :             gdsMeta->projType = GS3_LATLON;
     892                 :             break;
     893                 :          }
     894               4 :          gdsMeta->orientLon = 0;
     895               4 :          gdsMeta->meshLat = 0;
     896               4 :          gdsMeta->scaleLat1 = 0;
     897               4 :          gdsMeta->scaleLat2 = 0;
     898               4 :          gdsMeta->southLat = 0;
     899               4 :          gdsMeta->southLon = 0;
     900               4 :          gdsMeta->center = 0;
     901                 : 
     902               4 :          gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
     903               4 :          gds += 2;
     904               4 :          gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
     905               4 :          gds += 2;
     906               4 :          gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
     907               4 :          gds += 3;
     908               4 :          gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
     909               4 :          gds += 3;
     910                 : 
     911               4 :          gdsMeta->resFlag = *(gds++);
     912               4 :          if (gdsMeta->resFlag & 0x40) {
     913               0 :             gdsMeta->f_sphere = 0;
     914               0 :             gdsMeta->majEarth = 6378.160;
     915               0 :             gdsMeta->minEarth = 6356.775;
     916                 :          } else {
     917               4 :             gdsMeta->f_sphere = 1;
     918               4 :             gdsMeta->majEarth = 6367.47;
     919               4 :             gdsMeta->minEarth = 6367.47;
     920                 :          }
     921                 : 
     922               4 :          gdsMeta->lat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
     923               4 :          gds += 3;
     924               4 :          gdsMeta->lon2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
     925               4 :          gds += 3;
     926               4 :          gdsMeta->Dx = GRIB_UNSIGN_INT2 (*gds, gds[1]) * unit;
     927               4 :          gds += 2;
     928               4 :          if (gridType == GB1S2_GAUSSIAN_LATLON) {
     929               0 :             int np = GRIB_UNSIGN_INT2 (*gds, gds[1]); /* parallels between a pole and the equator */
     930               0 :             gdsMeta->Dy = 90.0 / np;
     931                 :          } else
     932               4 :             gdsMeta->Dy = GRIB_UNSIGN_INT2 (*gds, gds[1]) * unit;
     933               4 :          gds += 2;
     934               4 :          gdsMeta->scan = *gds;
     935               4 :          gdsMeta->f_typeLatLon = 0;
     936                 : #ifdef DEBUG
     937                 : /*
     938                 :          printf ("sectLen %ld\n", sectLen);
     939                 : */
     940                 : #endif
     941               4 :          if (sectLen == 42) {
     942                 :             /* Check if all 0's or all 1's, which means f_typeLatLon == 0 */
     943               0 :             f_allZero = 1;
     944               0 :             f_allOne = 1;
     945               0 :             for (i = 0; i < 10; i++) {
     946               0 :                if (gds[i] != 0)
     947               0 :                   f_allZero = 0;
     948               0 :                if (gds[i] != 255)
     949               0 :                   f_allOne = 0;
     950                 :             }
     951               0 :             if (!f_allZero && !f_allOne) {
     952               0 :                gdsMeta->f_typeLatLon = 1;
     953               0 :                gds += 5;
     954               0 :                gdsMeta->poleLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     955               0 :                                    unit);
     956               0 :                gds += 3;
     957               0 :                gdsMeta->poleLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     958               0 :                                    unit);
     959               0 :                gds += 3;
     960               0 :                MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
     961               0 :                gdsMeta->stretchFactor = fval_360 (uli_temp);
     962                 :             }
     963               4 :          } else if (sectLen == 52) {
     964               0 :             gds += 5;
     965                 :             /* Check if all 0's or all 1's, which means f_typeLatLon == 0 */
     966               0 :             f_allZero = 1;
     967               0 :             f_allOne = 1;
     968               0 :             for (i = 0; i < 20; i++) {
     969               0 :                if (gds[i] != 0)
     970               0 :                   f_allZero = 0;
     971               0 :                if (gds[i] != 255)
     972               0 :                   f_allOne = 0;
     973                 :             }
     974               0 :             if (!f_allZero && !f_allOne) {
     975               0 :                gdsMeta->f_typeLatLon = 2;
     976               0 :                gdsMeta->southLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     977               0 :                                     unit);
     978               0 :                gds += 3;
     979               0 :                gdsMeta->southLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     980               0 :                                     unit);
     981               0 :                gds += 3;
     982               0 :                MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
     983               0 :                gdsMeta->angleRotate = fval_360 (uli_temp);
     984               0 :                gds += 4;
     985               0 :                gdsMeta->poleLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     986               0 :                                    unit);
     987               0 :                gds += 3;
     988               0 :                gdsMeta->poleLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
     989               0 :                                    unit);
     990               0 :                gds += 3;
     991               0 :                MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
     992               0 :                gdsMeta->stretchFactor = fval_360 (uli_temp);
     993                 :             }
     994                 : #ifdef DEBUG
     995                 : /*
     996                 :             if (gdsMeta->lon2 == 360.25)
     997                 :                gdsMeta->lon2 = 359.75;
     998                 : */
     999                 : /*
    1000                 :             printf ("south %f %f rotate %f pole %f %f stretch %f\n",
    1001                 :                     gdsMeta->southLat, gdsMeta->southLon,
    1002                 :                     gdsMeta->angleRotate, gdsMeta->poleLat, gdsMeta->poleLon,
    1003                 :                     gdsMeta->stretchFactor);
    1004                 :             printf ("lat/lon type %d \n", gdsMeta->f_typeLatLon);
    1005                 : */
    1006                 : #endif
    1007                 :          }
    1008               4 :          break;
    1009                 : 
    1010                 :       case GB1S2_POLAR:
    1011               0 :          if (sectLen != 32) {
    1012               0 :             errSprintf ("For Polar GDS, should have 32 bytes of data\n");
    1013               0 :             return -1;
    1014                 :          }
    1015               0 :          gdsMeta->projType = GS3_POLAR;
    1016               0 :          gdsMeta->lat2 = 0;
    1017               0 :          gdsMeta->lon2 = 0;
    1018               0 :          gdsMeta->southLat = 0;
    1019               0 :          gdsMeta->southLon = 0;
    1020                 : 
    1021               0 :          gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1022               0 :          gds += 2;
    1023               0 :          gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1024               0 :          gds += 2;
    1025               0 :          gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1026               0 :          gds += 3;
    1027               0 :          gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1028               0 :          gds += 3;
    1029                 : 
    1030               0 :          gdsMeta->resFlag = *(gds++);
    1031               0 :          if (gdsMeta->resFlag & 0x40) {
    1032               0 :             gdsMeta->f_sphere = 0;
    1033               0 :             gdsMeta->majEarth = 6378.160;
    1034               0 :             gdsMeta->minEarth = 6356.775;
    1035                 :          } else {
    1036               0 :             gdsMeta->f_sphere = 1;
    1037               0 :             gdsMeta->majEarth = 6367.47;
    1038               0 :             gdsMeta->minEarth = 6367.47;
    1039                 :          }
    1040                 : 
    1041               0 :          gdsMeta->orientLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1042               0 :          gds += 3;
    1043               0 :          gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1044               0 :          gds += 3;
    1045               0 :          gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1046               0 :          gds += 3;
    1047               0 :          gdsMeta->meshLat = 60; /* Depends on hemisphere. */
    1048               0 :          gdsMeta->center = *(gds++);
    1049               0 :          if (gdsMeta->center & GRIB2BIT_1) {
    1050                 :             /* South polar stereographic. */
    1051               0 :             gdsMeta->scaleLat1 = gdsMeta->scaleLat2 = -90;
    1052                 :          } else {
    1053                 :             /* North polar stereographic. */
    1054               0 :             gdsMeta->scaleLat1 = gdsMeta->scaleLat2 = 90;
    1055                 :          }
    1056               0 :          gdsMeta->scan = *gds;
    1057               0 :          break;
    1058                 : 
    1059                 :       case GB1S2_LAMBERT:
    1060               0 :          if (sectLen != 42) {
    1061               0 :             errSprintf ("For Lambert GDS, should have 42 bytes of data\n");
    1062               0 :             return -1;
    1063                 :          }
    1064               0 :          gdsMeta->projType = GS3_LAMBERT;
    1065               0 :          gdsMeta->lat2 = 0;
    1066               0 :          gdsMeta->lon2 = 0;
    1067                 : 
    1068               0 :          gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1069               0 :          gds += 2;
    1070               0 :          gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1071               0 :          gds += 2;
    1072               0 :          gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1073               0 :          gds += 3;
    1074               0 :          gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1075               0 :          gds += 3;
    1076                 : 
    1077               0 :          gdsMeta->resFlag = *(gds++);
    1078               0 :          if (gdsMeta->resFlag & 0x40) {
    1079               0 :             gdsMeta->f_sphere = 0;
    1080               0 :             gdsMeta->majEarth = 6378.160;
    1081               0 :             gdsMeta->minEarth = 6356.775;
    1082                 :          } else {
    1083               0 :             gdsMeta->f_sphere = 1;
    1084               0 :             gdsMeta->majEarth = 6367.47;
    1085               0 :             gdsMeta->minEarth = 6367.47;
    1086                 :          }
    1087                 : 
    1088               0 :          gdsMeta->orientLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1089               0 :          gds += 3;
    1090               0 :          gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1091               0 :          gds += 3;
    1092               0 :          gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1093               0 :          gds += 3;
    1094               0 :          gdsMeta->center = *(gds++);
    1095               0 :          gdsMeta->scan = *(gds++);
    1096               0 :          gdsMeta->scaleLat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1097               0 :          gds += 3;
    1098               0 :          gdsMeta->scaleLat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1099               0 :          gds += 3;
    1100               0 :          gdsMeta->meshLat = gdsMeta->scaleLat1;
    1101               0 :          gdsMeta->southLat = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1102               0 :          gds += 3;
    1103               0 :          gdsMeta->southLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1104               0 :          break;
    1105                 : 
    1106                 :       case GB1S2_MERCATOR:
    1107               0 :          if (sectLen != 42) {
    1108               0 :             errSprintf ("For Mercator GDS, should have 42 bytes of data\n");
    1109               0 :             return -1;
    1110                 :          }
    1111               0 :          gdsMeta->projType = GS3_MERCATOR;
    1112               0 :          gdsMeta->southLat = 0;
    1113               0 :          gdsMeta->southLon = 0;
    1114               0 :          gdsMeta->orientLon = 0;
    1115               0 :          gdsMeta->center = 0;
    1116                 : 
    1117               0 :          gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1118               0 :          gds += 2;
    1119               0 :          gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
    1120               0 :          gds += 2;
    1121               0 :          gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1122               0 :          gds += 3;
    1123               0 :          gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1124               0 :          gds += 3;
    1125                 : 
    1126               0 :          gdsMeta->resFlag = *(gds++);
    1127               0 :          if (gdsMeta->resFlag & 0x40) {
    1128               0 :             gdsMeta->f_sphere = 0;
    1129               0 :             gdsMeta->majEarth = 6378.160;
    1130               0 :             gdsMeta->minEarth = 6356.775;
    1131                 :          } else {
    1132               0 :             gdsMeta->f_sphere = 1;
    1133               0 :             gdsMeta->majEarth = 6367.47;
    1134               0 :             gdsMeta->minEarth = 6367.47;
    1135                 :          }
    1136                 : 
    1137               0 :          gdsMeta->lat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1138               0 :          gds += 3;
    1139               0 :          gdsMeta->lon2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1140               0 :          gds += 3;
    1141               0 :          gdsMeta->scaleLat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
    1142               0 :          gds += 3;
    1143               0 :          gdsMeta->scaleLat2 = gdsMeta->scaleLat1;
    1144               0 :          gdsMeta->meshLat = gdsMeta->scaleLat1;
    1145                 :          /* Reserved set to 0. */
    1146               0 :          gds++;
    1147               0 :          gdsMeta->scan = *(gds++);
    1148               0 :          gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1149               0 :          gds += 3;
    1150               0 :          gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
    1151               0 :          break;
    1152                 : 
    1153                 :       default:
    1154               0 :          errSprintf ("Grid projection number is %d\n", gridType);
    1155               0 :          errSprintf ("Don't know how to handle this grid projection.\n");
    1156               0 :          return -2;
    1157                 :    }
    1158               4 :    gdsMeta->numPts = gdsMeta->Nx * gdsMeta->Ny;
    1159                 : #ifdef DEBUG
    1160                 : /*
    1161                 : printf ("NumPts = %ld\n", gdsMeta->numPts);
    1162                 : printf ("Nx = %ld, Ny = %ld\n", gdsMeta->Nx, gdsMeta->Ny);
    1163                 : */
    1164                 : #endif
    1165               4 :    return 0;
    1166                 : }
    1167                 : 
    1168                 : /*****************************************************************************
    1169                 :  * ReadGrib1Sect3() --
    1170                 :  *
    1171                 :  * Arthur Taylor / MDL
    1172                 :  *
    1173                 :  * PURPOSE
    1174                 :  *   Parses the GRIB1 "Bit Map Section" or section 3, filling out the bitmap
    1175                 :  * as needed.
    1176                 :  *
    1177                 :  * ARGUMENTS
    1178                 :  *     bms = The compressed part of the message dealing with "BMS". (Input)
    1179                 :  * gribLen = The total length of the GRIB1 message. (Input)
    1180                 :  *  curLoc = Current location in the GRIB1 message. (Output)
    1181                 :  *  bitmap = The extracted bitmap. (Output)
    1182                 :  *    NxNy = The total size of the grid. (Input)
    1183                 :  *
    1184                 :  * FILES/DATABASES: None
    1185                 :  *
    1186                 :  * RETURNS: int (could use errSprintf())
    1187                 :  *  0 = OK
    1188                 :  * -1 = gribLen is too small.
    1189                 :  * -2 = unexpected values in bms.
    1190                 :  *
    1191                 :  * HISTORY
    1192                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created.
    1193                 :  *
    1194                 :  * NOTES
    1195                 :  *****************************************************************************
    1196                 :  */
    1197               3 : static int ReadGrib1Sect3 (uChar *bms, uInt4 gribLen, uInt4 *curLoc,
    1198                 :                            uChar *bitmap, uInt4 NxNy)
    1199                 : {
    1200                 :    uInt4 sectLen;       /* Length in bytes of the current section. */
    1201                 :    short int numeric;   /* Determine if this is a predefined bitmap */
    1202                 :    uChar bits;          /* Used to locate which bit we are currently using. */
    1203                 :    uInt4 i;             /* Helps traverse the bitmap. */
    1204                 : 
    1205               3 :    sectLen = GRIB_UNSIGN_INT3 (*bms, bms[1], bms[2]);
    1206                 : #ifdef DEBUG
    1207                 : /*
    1208                 :    printf ("Section 3 length = %ld\n", sectLen);
    1209                 : */
    1210                 : #endif
    1211               3 :    *curLoc += sectLen;
    1212               3 :    if (*curLoc > gribLen) {
    1213               0 :       errSprintf ("Ran out of data in BMS (GRIB 1 Section 3)\n");
    1214               0 :       return -1;
    1215                 :    }
    1216               3 :    bms += 3;
    1217                 :    /* Assert: *bms currently points to number of unused bits at end of BMS. */
    1218               3 :    if (NxNy + *bms + 6 * 8 != sectLen * 8) {
    1219                 :       errSprintf ("NxNy + # of unused bits %ld != # of available bits %ld\n",
    1220               0 :                   (sInt4) (NxNy + *bms), (sInt4) ((sectLen - 6) * 8));
    1221               0 :       return -2;
    1222                 :    }
    1223               3 :    bms++;
    1224                 :    /* Assert: Non-zero "numeric" means predefined bitmap. */
    1225               3 :    numeric = GRIB_UNSIGN_INT2 (*bms, bms[1]);
    1226               3 :    bms += 2;
    1227               3 :    if (numeric != 0) {
    1228               0 :       errSprintf ("Don't handle predefined bitmaps yet.\n");
    1229               0 :       return -2;
    1230                 :    }
    1231               3 :    bits = 0x80;
    1232           17805 :    for (i = 0; i < NxNy; i++) {
    1233           17802 :       *(bitmap++) = (*bms) & bits;
    1234           17802 :       bits = bits >> 1;
    1235           17802 :       if (bits == 0) {
    1236            2224 :          bms++;
    1237            2224 :          bits = 0x80;
    1238                 :       }
    1239                 :    }
    1240               3 :    return 0;
    1241                 : }
    1242                 : 
    1243               0 : static int UnpackCmplx (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
    1244                 :                         short int DSF, double *data, grib_MetaData *meta,
    1245                 :                         char f_bms, uChar *bitmap, double unitM,
    1246                 :                         double unitB, short int ESF, double refVal,
    1247                 :                         uChar numBits, uChar f_octet14)
    1248                 : {
    1249                 :    uInt4 secLen;
    1250                 :    int N1;
    1251                 :    int N2;
    1252                 :    int P1;
    1253                 :    int P2;
    1254                 :    uChar octet14;
    1255                 :    uChar f_maxtrixValues;
    1256               0 :    uChar f_secBitmap = 0;
    1257                 :    uChar f_secValDiffWid;
    1258                 :    int i;
    1259                 :    uInt4 uli_temp;      /* Used to store sInt4s (temporarily) */
    1260                 :    uChar bufLoc;        /* Keeps track of where to start getting more data
    1261                 :                          * out of the packed data stream. */
    1262                 :    size_t numUsed;      /* How many bytes were used in a given call to
    1263                 :                          * memBitRead. */
    1264                 :    uChar *width;
    1265                 : 
    1266               0 :    secLen = 11;
    1267               0 :    N1 = GRIB_UNSIGN_INT2 (bds[0], bds[1]);
    1268               0 :    octet14 = bds[2];
    1269               0 :    printf ("octet14, %d\n", octet14);
    1270               0 :    if (f_octet14) {
    1271               0 :       f_maxtrixValues = octet14 & GRIB2BIT_2;
    1272               0 :       f_secBitmap = octet14 & GRIB2BIT_3;
    1273               0 :       f_secValDiffWid = octet14 & GRIB2BIT_4;
    1274                 :       printf ("f_matrixValues, f_secBitmap, f_secValeDiffWid %d %d %d\n",
    1275               0 :               f_maxtrixValues, f_secBitmap, f_secValDiffWid);
    1276                 :    }
    1277               0 :    N2 = GRIB_UNSIGN_INT2 (bds[3], bds[4]);
    1278               0 :    P1 = GRIB_UNSIGN_INT2 (bds[5], bds[6]);
    1279               0 :    P2 = GRIB_UNSIGN_INT2 (bds[7], bds[8]);
    1280               0 :    printf ("N1 N2 P1 P2 : %d %d %d %d\n", N1, N2, P1, P2);
    1281               0 :    printf ("Reserved %d\n", bds[9]);
    1282               0 :    bds += 10;
    1283               0 :    secLen += 10;
    1284                 : 
    1285               0 :    width = (uChar *) malloc (P1 * sizeof (uChar));
    1286                 : 
    1287               0 :    for (i = 0; i < P1; i++) {
    1288               0 :       width[i] = *bds;
    1289               0 :       printf ("(Width %d %d)\n", i, width[i]);
    1290               0 :       bds++;
    1291               0 :       secLen++;
    1292                 :    }
    1293               0 :    if (f_secBitmap) {
    1294               0 :       bufLoc = 8;
    1295               0 :       for (i = 0; i < P2; i++) {
    1296               0 :          memBitRead (&uli_temp, sizeof (sInt4), bds, 1, &bufLoc, &numUsed);
    1297               0 :          printf ("(%d %d) ", i, uli_temp);
    1298               0 :          if (numUsed != 0) {
    1299               0 :             printf ("\n");
    1300               0 :             bds += numUsed;
    1301               0 :             secLen++;
    1302                 :          }
    1303                 :       }
    1304               0 :       if (bufLoc != 8) {
    1305               0 :          bds++;
    1306               0 :          secLen++;
    1307                 :       }
    1308               0 :       printf ("Observed Sec Len %d\n", secLen);
    1309                 :    } else {
    1310                 :       /* Jump over widths and secondary bitmap */
    1311               0 :       bds += (N1 - 21);
    1312               0 :       secLen += (N1 - 21);
    1313                 :    }
    1314                 : 
    1315               0 :    bufLoc = 8;
    1316               0 :    for (i = 0; i < P1; i++) {
    1317               0 :       memBitRead (&uli_temp, sizeof (sInt4), bds, numBits, &bufLoc, &numUsed);
    1318                 :       printf ("(%d %d) (numUsed %ld numBits %d)", i, uli_temp, 
    1319               0 :               (long) numUsed, numBits);
    1320               0 :       if (numUsed != 0) {
    1321               0 :          printf ("\n");
    1322               0 :          bds += numUsed;
    1323               0 :          secLen++;
    1324                 :       }
    1325                 :    }
    1326               0 :    if (bufLoc != 8) {
    1327               0 :       bds++;
    1328               0 :       secLen++;
    1329                 :    }
    1330                 : 
    1331               0 :    printf ("Observed Sec Len %d\n", secLen);
    1332               0 :    printf ("N2 = %d\n", N2);
    1333                 : 
    1334               0 :    errSprintf ("Don't know how to handle Complex GRIB1 packing yet.\n");
    1335               0 :    free (width);
    1336               0 :    return -2;
    1337                 : 
    1338                 : }
    1339                 : 
    1340                 : /*****************************************************************************
    1341                 :  * ReadGrib1Sect4() --
    1342                 :  *
    1343                 :  * Arthur Taylor / MDL
    1344                 :  *
    1345                 :  * PURPOSE
    1346                 :  *   Unpacks the "Binary Data Section" or section 4.
    1347                 :  *
    1348                 :  * ARGUMENTS
    1349                 :  *     bds = The compressed part of the message dealing with "BDS". (Input)
    1350                 :  * gribLen = The total length of the GRIB1 message. (Input)
    1351                 :  *  curLoc = Current location in the GRIB1 message. (Output)
    1352                 :  *     DSF = Decimal Scale Factor for unpacking the data. (Input)
    1353                 :  *    data = The extracted grid. (Output)
    1354                 :  *    meta = The meta data associated with the grid (Input/Output)
    1355                 :  *   f_bms = True if bitmap is to be used. (Input)
    1356                 :  *  bitmap = 0 if missing data, 1 if valid data. (Input)
    1357                 :  *   unitM = The M unit conversion value in equation y = Mx + B. (Input)
    1358                 :  *   unitB = The B unit conversion value in equation y = Mx + B. (Input)
    1359                 :  *
    1360                 :  * FILES/DATABASES: None
    1361                 :  *
    1362                 :  * RETURNS: int (could use errSprintf())
    1363                 :  *  0 = OK
    1364                 :  * -1 = gribLen is too small.
    1365                 :  * -2 = unexpected values in bds.
    1366                 :  *
    1367                 :  * HISTORY
    1368                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
    1369                 :  *   3/2004 AAT: Switched {# Pts * (# Bits in a Group) +
    1370                 :  *          # of unused bits != # of available bits} to a warning from an
    1371                 :  *          error.
    1372                 :  *
    1373                 :  * NOTES
    1374                 :  * 1) See metaparse.c : ParseGrid()
    1375                 :  * 2) Currently, only handles "Simple pack".
    1376                 :  *****************************************************************************
    1377                 :  */
    1378               4 : static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
    1379                 :                            short int DSF, double *data, grib_MetaData *meta,
    1380                 :                            char f_bms, uChar *bitmap, double unitM,
    1381                 :                            double unitB)
    1382                 : {
    1383                 :    uInt4 sectLen;       /* Length in bytes of the current section. */
    1384                 :    short int ESF;       /* Power of 2 scaling factor. */
    1385                 :    uInt4 uli_temp;      /* Used to store sInt4s (temporarily) */
    1386                 :    double refVal;       /* The refrence value for the grid, also the minimum
    1387                 :                          * value. */
    1388                 :    uChar numBits;       /* # of bits for a single element of data. */
    1389                 :    uChar numUnusedBit;  /* # of extra bits at end of record. */
    1390                 :    uChar f_spherHarm;   /* Flag if data contains Spherical Harmonics. */
    1391                 :    uChar f_cmplxPack;   /* Flag if complex packing was used. */
    1392                 :    uChar f_octet14;     /* Flag if octet 14 was used. */
    1393                 :    uChar bufLoc;        /* Keeps track of where to start getting more data
    1394                 :                          * out of the packed data stream. */
    1395                 :    uChar f_convert;     /* Determine if scan mode implies that we have to do
    1396                 :                          * manipulation as we read the grid to get desired
    1397                 :                          * internal scan mode. */
    1398                 :    uInt4 i;             /* Used to traverse the grid. */
    1399                 :    size_t numUsed;      /* How many bytes were used in a given call to
    1400                 :                          * memBitRead. */
    1401                 :    double d_temp;       /* Holds the extracted data until we put it in data */
    1402                 :    sInt4 newIndex;      /* Where to put the answer (primarily if f_convert) */
    1403                 :    sInt4 x;             /* Used to help compute newIndex , if f_convert. */
    1404                 :    sInt4 y;             /* Used to help compute newIndex , if f_convert. */
    1405                 :    double resetPrim;    /* If possible, used to reset the primary missing
    1406                 :                          * value from 9.999e20 to a reasonable # (9999) */
    1407                 : 
    1408               4 :    if (meta->gds.Nx * meta->gds.Ny != meta->gds.numPts) {
    1409               0 :       errSprintf ("(Nx * Ny != numPts) ?? in BDS (GRIB 1 Section 4)\n");
    1410               0 :       return -2;
    1411                 :    }
    1412               4 :    sectLen = GRIB_UNSIGN_INT3 (*bds, bds[1], bds[2]);
    1413                 : #ifdef DEBUG
    1414                 : /*
    1415                 :    printf ("Section 4 length = %ld\n", sectLen);
    1416                 : */
    1417                 : #endif
    1418               4 :    *curLoc += sectLen;
    1419               4 :    if (*curLoc > gribLen) {
    1420               0 :       errSprintf ("Ran out of data in BDS (GRIB 1 Section 4)\n");
    1421               0 :       return -1;
    1422                 :    }
    1423               4 :    bds += 3;
    1424                 : 
    1425                 :    /* Assert: bds now points to the main pack flag. */
    1426               4 :    f_spherHarm = (*bds) & GRIB2BIT_1;
    1427               4 :    f_cmplxPack = (*bds) & GRIB2BIT_2;
    1428               4 :    meta->gridAttrib.fieldType = (*bds) & GRIB2BIT_3;
    1429               4 :    f_octet14 = (*bds) & GRIB2BIT_4;
    1430                 : 
    1431               4 :    numUnusedBit = (*bds) & 0x0f;
    1432                 : #ifdef DEBUG
    1433                 : /*
    1434                 :    printf ("bds byte flag = %d\n", *bds);
    1435                 :    printf ("Number of unused bits = %d\n", numUnusedBit);
    1436                 : */
    1437                 : #endif
    1438               4 :    if (f_spherHarm) {
    1439               0 :       errSprintf ("Don't know how to handle Spherical Harmonics yet.\n");
    1440               0 :       return -2;
    1441                 :    }
    1442                 : /*
    1443                 :    if (f_octet14) {
    1444                 :       errSprintf ("Don't know how to handle Octet 14 data yet.\n");
    1445                 :       errSprintf ("bds byte flag = %d\n", *bds);
    1446                 :       errSprintf ("bds byte: %d %d %d %d\n", f_spherHarm, f_cmplxPack,
    1447                 :                   meta->gridAttrib.fieldType, f_octet14);
    1448                 :       return -2;
    1449                 :    }
    1450                 : */
    1451               4 :    if (f_cmplxPack) {
    1452               0 :       meta->gridAttrib.packType = 2;
    1453                 :    } else {
    1454               4 :       meta->gridAttrib.packType = 0;
    1455                 :    }
    1456               4 :    bds++;
    1457                 : 
    1458                 :    /* Assert: bds now points to E (power of 2 scaling factor). */
    1459               4 :    ESF = GRIB_SIGN_INT2 (*bds, bds[1]);
    1460               4 :    bds += 2;
    1461               4 :    MEMCPY_BIG (&uli_temp, bds, sizeof (sInt4));
    1462               4 :    refVal = fval_360 (uli_temp);
    1463               4 :    bds += 4;
    1464                 : 
    1465                 :    /* Assert: bds is now the number of bits in a group. */
    1466               4 :    numBits = *bds;
    1467                 : /*
    1468                 : #ifdef DEBUG
    1469                 :    printf ("refValue %f numBits %d\n", refVal, numBits);
    1470                 :    printf ("ESF %d DSF %d\n", ESF, DSF);
    1471                 : #endif
    1472                 : */
    1473               4 :    if (f_cmplxPack) {
    1474               0 :       bds++;
    1475                 : #ifdef DEBUG
    1476                 :       return UnpackCmplx (bds, gribLen, curLoc, DSF, data, meta, f_bms,
    1477                 :                           bitmap, unitM, unitB, ESF, refVal, numBits,
    1478                 :                           f_octet14);
    1479                 : #else
    1480               0 :       errSprintf ("Don't know how to handle Complex GRIB1 packing yet.\n");
    1481               0 :       return -2;
    1482                 : #endif
    1483                 :    }
    1484                 : 
    1485               4 :    if (!f_bms && (meta->gds.numPts * numBits + numUnusedBit) !=
    1486                 :        (sectLen - 11) * 8) {
    1487                 :       printf ("numPts * (numBits in a Group) + # of unused bits %d != "
    1488                 :               "# of available bits %d\n",
    1489                 :               (sInt4) (meta->gds.numPts * numBits + numUnusedBit),
    1490               0 :               (sInt4) ((sectLen - 11) * 8));
    1491                 : /*
    1492                 :       errSprintf ("numPts * (numBits in a Group) + # of unused bits %ld != "
    1493                 :                   "# of available bits %ld\n",
    1494                 :                   (sInt4) (meta->gds.numPts * numBits + numUnusedBit),
    1495                 :                   (sInt4) ((sectLen - 11) * 8));
    1496                 :       return -2;
    1497                 : */
    1498                 :    }
    1499               4 :    if (numBits > 32) {
    1500               0 :       errSprintf ("The number of bits per number is larger than 32?\n");
    1501               0 :       return -2;
    1502                 :    }
    1503               4 :    bds++;
    1504                 : 
    1505                 :    /* Convert Units. */
    1506               4 :    if (unitM == -10) {
    1507                 :       meta->gridAttrib.min = pow (10.0, (refVal * pow (2.0, ESF) /
    1508               0 :                                        pow (10.0, DSF)));
    1509                 :    } else {
    1510                 : /*      meta->gridAttrib.min = unitM * (refVal / pow (10.0, DSF)) + unitB; */
    1511                 :       meta->gridAttrib.min = unitM * (refVal * pow (2.0, ESF) /
    1512               4 :                                       pow (10.0, DSF)) + unitB;
    1513                 :    }
    1514               4 :    meta->gridAttrib.max = meta->gridAttrib.min;
    1515               4 :    meta->gridAttrib.f_maxmin = 1;
    1516               4 :    meta->gridAttrib.numMiss = 0;
    1517               4 :    meta->gridAttrib.refVal = refVal;
    1518               4 :    meta->gridAttrib.ESF = ESF;
    1519               4 :    meta->gridAttrib.DSF = DSF;
    1520               4 :    bufLoc = 8;
    1521                 :    /* Internally we use scan = 0100.  Scan is usually 0100 but if need be, we
    1522                 :     * can convert it. */
    1523               4 :    f_convert = ((meta->gds.scan & 0xe0) != 0x40);
    1524                 : 
    1525               4 :    if (f_bms) {
    1526                 : /*
    1527                 : #ifdef DEBUG
    1528                 :       printf ("There is a bitmap?\n");
    1529                 : #endif
    1530                 : */
    1531                 :       /* Start unpacking the data, assuming there is a bitmap. */
    1532               3 :       meta->gridAttrib.f_miss = 1;
    1533               3 :       meta->gridAttrib.missPri = UNDEFINED;
    1534           17805 :       for (i = 0; i < meta->gds.numPts; i++) {
    1535                 :          /* Find the destination index. */
    1536           17802 :          if (f_convert) {
    1537                 :             /* ScanIndex2XY returns value as if scan was 0100 */
    1538                 :             ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
    1539               0 :                           meta->gds.Ny);
    1540               0 :             newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
    1541                 :          } else {
    1542           17802 :             newIndex = i;
    1543                 :          }
    1544                 :          /* A 0 in bitmap means no data. A 1 in bitmap means data. */
    1545           17802 :          if (!bitmap[i]) {
    1546            7542 :             meta->gridAttrib.numMiss++;
    1547            7542 :             data[newIndex] = UNDEFINED;
    1548                 :          } else {
    1549           10260 :             if (numBits != 0) {
    1550                 :                memBitRead (&uli_temp, sizeof (sInt4), bds, numBits,
    1551           10260 :                            &bufLoc, &numUsed);
    1552           10260 :                bds += numUsed;
    1553           10260 :                d_temp = (refVal + (uli_temp * pow (2.0, ESF))) / pow (10.0, DSF);
    1554                 :                /* Convert Units. */
    1555           10260 :                if (unitM == -10) {
    1556               0 :                   d_temp = pow (10.0, d_temp);
    1557                 :                } else {
    1558           10260 :                   d_temp = unitM * d_temp + unitB;
    1559                 :                }
    1560           10260 :                if (meta->gridAttrib.max < d_temp) {
    1561              16 :                   meta->gridAttrib.max = d_temp;
    1562                 :                }
    1563           10260 :                data[newIndex] = d_temp;
    1564                 :             } else {
    1565                 :                /* Assert: d_temp = unitM * refVal / pow (10.0,DSF) + unitB. */
    1566                 :                /* Assert: min = unitM * refVal / pow (10.0, DSF) + unitB. */
    1567               0 :                data[newIndex] = meta->gridAttrib.min;
    1568                 :             }
    1569                 :          }
    1570                 :       }
    1571                 :       /* Reset the missing value to UNDEFINED_PRIM if possible.  If not
    1572                 :        * possible, make sure UNDEFINED is outside the range.  If UNDEFINED
    1573                 :        * is_ in the range, choose max + 1 for missing. */
    1574               3 :       resetPrim = 0;
    1575               5 :       if ((meta->gridAttrib.max < UNDEFINED_PRIM) ||
    1576                 :           (meta->gridAttrib.min > UNDEFINED_PRIM)) {
    1577               2 :          resetPrim = UNDEFINED_PRIM;
    1578               1 :       } else if ((meta->gridAttrib.max >= UNDEFINED) &&
    1579                 :                  (meta->gridAttrib.min <= UNDEFINED)) {
    1580               0 :          resetPrim = meta->gridAttrib.max + 1;
    1581                 :       }
    1582               3 :       if (resetPrim != 0) {
    1583               2 :          meta->gridAttrib.missPri = resetPrim;
    1584           12920 :          for (i = 0; i < meta->gds.numPts; i++) {
    1585                 :             /* Find the destination index. */
    1586           12918 :             if (f_convert) {
    1587                 :                /* ScanIndex2XY returns value as if scan was 0100 */
    1588                 :                ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
    1589               0 :                              meta->gds.Ny);
    1590               0 :                newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
    1591                 :             } else {
    1592           12918 :                newIndex = i;
    1593                 :             }
    1594           12918 :             if (!bitmap[i]) {
    1595            4852 :                data[newIndex] = resetPrim;
    1596                 :             }
    1597                 :          }
    1598                 :       }
    1599                 : 
    1600                 :    } else {
    1601                 : 
    1602                 : #ifdef DEBUG
    1603                 : /*
    1604                 :       printf ("There is no bitmap?\n");
    1605                 : */
    1606                 : #endif
    1607                 : 
    1608                 :       /* Start unpacking the data, assuming there is NO bitmap. */
    1609               1 :       meta->gridAttrib.f_miss = 0;
    1610             589 :       for (i = 0; i < meta->gds.numPts; i++) {
    1611             588 :          if (numBits != 0) {
    1612                 :             /* Find the destination index. */
    1613             588 :             if (f_convert) {
    1614                 :                /* ScanIndex2XY returns value as if scan was 0100 */
    1615                 :                ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
    1616             588 :                              meta->gds.Ny);
    1617             588 :                newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
    1618                 :             } else {
    1619               0 :                newIndex = i;
    1620                 :             }
    1621                 : 
    1622                 :             memBitRead (&uli_temp, sizeof (sInt4), bds, numBits, &bufLoc,
    1623             588 :                         &numUsed);
    1624             588 :             bds += numUsed;
    1625             588 :             d_temp = (refVal + (uli_temp * pow (2.0, ESF))) / pow (10.0, DSF);
    1626                 : 
    1627                 : #ifdef DEBUG
    1628                 : /*
    1629                 :             if (i == 1) {
    1630                 :                printf ("refVal %f, uli_temp %ld, ans %f\n", refVal, uli_temp,
    1631                 :                        d_temp);
    1632                 :                printf ("numBits %d, bufLoc %d, numUsed %d\n", numBits,
    1633                 :                        bufLoc, numUsed);
    1634                 :             }
    1635                 : */
    1636                 : #endif
    1637                 : 
    1638                 :             /* Convert Units. */
    1639             588 :             if (unitM == -10) {
    1640               0 :                d_temp = pow (10.0, d_temp);
    1641                 :             } else {
    1642             588 :                d_temp = unitM * d_temp + unitB;
    1643                 :             }
    1644             588 :             if (meta->gridAttrib.max < d_temp) {
    1645              19 :                meta->gridAttrib.max = d_temp;
    1646                 :             }
    1647             588 :             data[newIndex] = d_temp;
    1648                 :          } else {
    1649                 :             /* Assert: whole array = unitM * refVal + unitB. */
    1650                 :             /* Assert: *min = unitM * refVal + unitB. */
    1651               0 :             data[i] = meta->gridAttrib.min;
    1652                 :          }
    1653                 :       }
    1654                 :    }
    1655               4 :    return 0;
    1656                 : }
    1657                 : 
    1658                 : /*****************************************************************************
    1659                 :  * ReadGrib1Record() --
    1660                 :  *
    1661                 :  * Arthur Taylor / MDL
    1662                 :  *
    1663                 :  * PURPOSE
    1664                 :  *   Reads in a GRIB1 message, and parses the data into various data
    1665                 :  * structures, for use with other code.
    1666                 :  *
    1667                 :  * ARGUMENTS
    1668                 :  *           fp = An opened GRIB2 file already at the correct message. (Input)
    1669                 :  *       f_unit = 0 use GRIB2 units, 1 use English, 2 use metric. (Input)
    1670                 :  *    Grib_Data = The read in GRIB2 grid. (Output)
    1671                 :  * grib_DataLen = Size of Grib_Data. (Output)
    1672                 :  *         meta = A filled in meta structure (Output)
    1673                 :  *           IS = The structure containing all the arrays that the
    1674                 :  *                unpacker uses (Output)
    1675                 :  *        sect0 = Already read in section 0 data. (Input)
    1676                 :  *      gribLen = Length of the GRIB1 message. (Input)
    1677                 :  *     majEarth = Used to override the GRIB major axis of earth. (Input)
    1678                 :  *     minEarth = Used to override the GRIB minor axis of earth. (Input)
    1679                 :  *
    1680                 :  * FILES/DATABASES:
    1681                 :  *   An already opened file pointing to the desired GRIB1 message.
    1682                 :  *
    1683                 :  * RETURNS: int (could use errSprintf())
    1684                 :  *  0 = OK
    1685                 :  * -1 = Problems reading in the PDS.
    1686                 :  * -2 = Problems reading in the GDS.
    1687                 :  * -3 = Problems reading in the BMS.
    1688                 :  * -4 = Problems reading in the BDS.
    1689                 :  * -5 = Problems reading the closing section.
    1690                 :  *
    1691                 :  * HISTORY
    1692                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
    1693                 :  *   5/2003 AAT: Was not updating offset.  It should be updated by
    1694                 :  *               calling routine anyways, so I got rid of the parameter.
    1695                 :  *   7/2003 AAT: Allowed user to override the radius of earth.
    1696                 :  *   8/2003 AAT: Found a memory Leak (Had been setting unitName to NULL).
    1697                 :  *   2/2004 AAT: Added maj/min earth override.
    1698                 :  *   3/2004 AAT: Added ability to change units.
    1699                 :  *
    1700                 :  * NOTES
    1701                 :  * 1) Could also compare GDS with the one specified by gridID
    1702                 :  * 2) Could add gridID support.
    1703                 :  * 3) Should add unitM / unitB support.
    1704                 :  *****************************************************************************
    1705                 :  */
    1706               4 : int ReadGrib1Record (DataSource &fp, sChar f_unit, double **Grib_Data,
    1707                 :                      uInt4 *grib_DataLen, grib_MetaData *meta,
    1708                 :                      IS_dataType *IS, sInt4 sect0[SECT0LEN_WORD],
    1709                 :                      uInt4 gribLen, double majEarth, double minEarth)
    1710                 : {
    1711                 :    sInt4 nd5;           /* Size of grib message rounded up to the nearest *
    1712                 :                          * sInt4. */
    1713                 :    uChar *c_ipack;      /* A char ptr to the message stored in IS->ipack */
    1714                 :    uInt4 curLoc;        /* Current location in the GRIB message. */
    1715                 :    char f_gds;          /* flag if there is a gds section. */
    1716                 :    char f_bms;          /* flag if there is a bms section. */
    1717                 :    double *grib_Data;   /* A pointer to Grib_Data for ease of manipulation. */
    1718               4 :    uChar *bitmap = NULL; /* A char field (0=noData, 1=data) set up in BMS. */
    1719                 :    short int DSF;       /* Decimal Scale Factor for unpacking the data. */
    1720               4 :    double unitM = 1;    /* M in y = Mx + B, for unit conversion. */
    1721               4 :    double unitB = 0;    /* B in y = Mx + B, for unit conversion. */
    1722                 :    uChar gridID;        /* Which GDS specs to use. */
    1723                 :    const char *varName; /* The name of the data stored in the grid. */
    1724                 :    const char *varComment; /* Extra comments about the data stored in grid. */
    1725                 :    const char *varUnit; /* Holds the name of the unit [K] [%] .. etc */
    1726                 :    sInt4 li_temp;       /* Used to make sure section 5 is 7777. */
    1727                 :    char unitName[15];   /* Holds the string name of the current unit. */
    1728                 :    int unitLen;         /* String length of string name of current unit. */
    1729                 : 
    1730                 :    /* Make room for entire message, and read it in. */
    1731                 :    /* nd5 needs to be gribLen in (sInt4) units rounded up. */
    1732               4 :    nd5 = (gribLen + 3) / 4;
    1733               4 :    if (nd5 > IS->ipackLen) {
    1734               4 :       IS->ipackLen = nd5;
    1735                 :       IS->ipack = (sInt4 *) realloc ((void *) (IS->ipack),
    1736               4 :                                      (IS->ipackLen) * sizeof (sInt4));
    1737                 :    }
    1738               4 :    c_ipack = (uChar *) IS->ipack;
    1739                 :    /* Init last sInt4 to 0, to make sure that the padded bytes are 0. */
    1740               4 :    IS->ipack[nd5 - 1] = 0;
    1741                 :    /* Init first 2 sInt4 to sect0. */
    1742               4 :    memcpy (c_ipack, sect0, SECT0LEN_WORD * 2);
    1743                 :    /* Read in the rest of the message. */
    1744               4 :    if (fp.DataSourceFread (c_ipack + SECT0LEN_WORD * 2, sizeof (char),
    1745               4 :               (gribLen - SECT0LEN_WORD * 2)) + SECT0LEN_WORD * 2 != gribLen) {
    1746               0 :       errSprintf ("Ran out of file\n");
    1747               0 :       return -1;
    1748                 :    }
    1749                 : 
    1750                 :    /* Preceeding was in degrib2, next part is specific to GRIB1. */
    1751               4 :    curLoc = 8;
    1752               4 :    if (ReadGrib1Sect1 (c_ipack + curLoc, gribLen, &curLoc, &(meta->pds1),
    1753                 :                        &f_gds, &gridID, &f_bms, &DSF, &(meta->center),
    1754                 :                        &(meta->subcenter)) != 0) {
    1755               0 :       preErrSprintf ("Inside ReadGrib1Record\n");
    1756               0 :       return -1;
    1757                 :    }
    1758                 : 
    1759                 :    /* Get the Grid Definition Section. */
    1760               4 :    if (f_gds) {
    1761               4 :       if (ReadGrib1Sect2 (c_ipack + curLoc, gribLen, &curLoc,
    1762                 :                           &(meta->gds)) != 0) {
    1763               0 :          preErrSprintf ("Inside ReadGrib1Record\n");
    1764               0 :          return -2;
    1765                 :       }
    1766                 :       /* Could also compare GDS with the one specified by gridID? */
    1767                 :    } else {
    1768               0 :       errSprintf ("Don't know how to handle a gridID lookup yet.\n");
    1769               0 :       return -2;
    1770                 :    }
    1771               4 :    meta->pds1.gridID = gridID;
    1772                 :    /* Allow data originating from NCEP to be 6371.2 by default. */
    1773               4 :    if ((meta->center == NMC)) {
    1774               4 :       if (meta->gds.majEarth == 6367.47) {
    1775               4 :          meta->gds.f_sphere = 1;
    1776               4 :          meta->gds.majEarth = 6371.2;
    1777               4 :          meta->gds.minEarth = 6371.2;
    1778                 :       }
    1779                 :    }
    1780               4 :    if ((majEarth > 6300) && (majEarth < 6400)) {
    1781               0 :       if ((minEarth > 6300) && (minEarth < 6400)) {
    1782               0 :          meta->gds.f_sphere = 0;
    1783               0 :          meta->gds.majEarth = majEarth;
    1784               0 :          meta->gds.minEarth = minEarth;
    1785               0 :          if (majEarth == minEarth) {
    1786               0 :             meta->gds.f_sphere = 1;
    1787                 :          }
    1788                 :       } else {
    1789               0 :          meta->gds.f_sphere = 1;
    1790               0 :          meta->gds.majEarth = majEarth;
    1791               0 :          meta->gds.minEarth = majEarth;
    1792                 :       }
    1793                 :    }
    1794                 : 
    1795                 :    /* Allocate memory for the grid. */
    1796               4 :    if (meta->gds.numPts > *grib_DataLen) {
    1797               4 :       *grib_DataLen = meta->gds.numPts;
    1798                 :       *Grib_Data = (double *) realloc ((void *) (*Grib_Data),
    1799               4 :                                        (*grib_DataLen) * sizeof (double));
    1800                 :    }
    1801               4 :    grib_Data = *Grib_Data;
    1802                 : 
    1803                 :    /* Get the Bit Map Section. */
    1804               4 :    if (f_bms) {
    1805               3 :       bitmap = (uChar *) malloc (meta->gds.numPts * sizeof (char));
    1806               3 :       if (ReadGrib1Sect3 (c_ipack + curLoc, gribLen, &curLoc, bitmap,
    1807                 :                           meta->gds.numPts) != 0) {
    1808               0 :          free (bitmap);
    1809               0 :          preErrSprintf ("Inside ReadGrib1Record\n");
    1810               0 :          return -3;
    1811                 :       }
    1812                 :    }
    1813                 : 
    1814                 :    /* Figure out some basic stuff about the grid. */
    1815                 :    /* Following is similar to metaparse.c : ParseElemName */
    1816                 :    GRIB1_Table2LookUp (&(meta->pds1), &varName, &varComment, &varUnit,
    1817               4 :                        &(meta->convert), meta->center, meta->subcenter);
    1818                 :    meta->element = (char *) realloc ((void *) (meta->element),
    1819               4 :                                      (1 + strlen (varName)) * sizeof (char));
    1820               4 :    strcpy (meta->element, varName);
    1821                 :    meta->unitName = (char *) realloc ((void *) (meta->unitName),
    1822                 :                                       (1 + 2 + strlen (varUnit)) *
    1823               4 :                                       sizeof (char));
    1824               4 :    sprintf (meta->unitName, "[%s]", varUnit);
    1825                 :    meta->comment = (char *) realloc ((void *) (meta->comment),
    1826                 :                                      (1 + strlen (varComment) +
    1827                 :                                       strlen (varUnit)
    1828               4 :                                       + 2 + 1) * sizeof (char));
    1829               4 :    sprintf (meta->comment, "%s [%s]", varComment, varUnit);
    1830                 : 
    1831               4 :    if (ComputeUnit (meta->convert, meta->unitName, f_unit, &unitM, &unitB,
    1832                 :                     unitName) == 0) {
    1833               0 :       unitLen = strlen (unitName);
    1834                 :       meta->unitName = (char *) realloc ((void *) (meta->unitName),
    1835               0 :                                          1 + unitLen * sizeof (char));
    1836               0 :       strncpy (meta->unitName, unitName, unitLen);
    1837               0 :       meta->unitName[unitLen] = '\0';
    1838                 :    }
    1839                 : 
    1840                 :    /* Read the GRID. */
    1841               4 :    if (ReadGrib1Sect4 (c_ipack + curLoc, gribLen, &curLoc, DSF, grib_Data,
    1842                 :                        meta, f_bms, bitmap, unitM, unitB) != 0) {
    1843               0 :       free (bitmap);
    1844               0 :       preErrSprintf ("Inside ReadGrib1Record\n");
    1845               0 :       return -4;
    1846                 :    }
    1847               4 :    if (f_bms) {
    1848               3 :       free (bitmap);
    1849                 :    }
    1850                 : 
    1851                 :    GRIB1_Table3LookUp (&(meta->pds1), &(meta->shortFstLevel),
    1852               4 :                        &(meta->longFstLevel));
    1853                 : /*   printf ("%s .. %s\n", meta->shortFstLevel, meta->longFstLevel);*/
    1854                 : 
    1855                 : /*
    1856                 :    strftime (meta->refTime, 20, "%Y%m%d%H%M",
    1857                 :              gmtime (&(meta->pds1.refTime)));
    1858                 : */
    1859               4 :    Clock_Print (meta->refTime, 20, meta->pds1.refTime, "%Y%m%d%H%M", 0);
    1860                 : 
    1861                 : /*
    1862                 :    strftime (meta->validTime, 20, "%Y%m%d%H%M",
    1863                 :              gmtime (&(meta->pds1.validTime)));
    1864                 : */
    1865               4 :    Clock_Print (meta->validTime, 20, meta->pds1.validTime, "%Y%m%d%H%M", 0);
    1866                 : 
    1867               4 :    meta->deltTime = (sInt4) (meta->pds1.validTime - meta->pds1.refTime);
    1868                 : 
    1869                 :    /* Read section 5.  If it is "7777" == 926365495 we are done. */
    1870               4 :    if (curLoc == gribLen) {
    1871                 :       printf ("Warning: either gribLen did not account for section 5, or "
    1872               0 :               "section 5 is missing\n");
    1873               0 :       return 0;
    1874                 :    }
    1875               4 :    if (curLoc + 4 > gribLen) {
    1876               0 :       errSprintf ("Ran out of bytes looking for the end of the message.\n");
    1877               0 :       return -5;
    1878                 :    }
    1879                 :    myAssert (curLoc + 4 == gribLen);
    1880               4 :    memcpy (&li_temp, c_ipack + curLoc, 4);
    1881               4 :    if (li_temp != 926365495L) {
    1882               0 :       errSprintf ("Did not find the end of the message.\n");
    1883               0 :       return -5;
    1884                 :    }
    1885                 : 
    1886               4 :    return 0;
    1887                 : }
    1888                 : 
    1889                 : /*****************************************************************************
    1890                 :  * main() --
    1891                 :  *
    1892                 :  * Arthur Taylor / MDL
    1893                 :  *
    1894                 :  * PURPOSE
    1895                 :  *   To test the capabilities of this module, and give an example as to how
    1896                 :  * ReadGrib1Record expects to be called.
    1897                 :  *
    1898                 :  * ARGUMENTS
    1899                 :  * argc = The number of arguments on the command line. (Input)
    1900                 :  * argv = The arguments on the command line. (Input)
    1901                 :  *
    1902                 :  * FILES/DATABASES:
    1903                 :  *   A GRIB1 file.
    1904                 :  *
    1905                 :  * RETURNS: int
    1906                 :  *  0 = OK
    1907                 :  *
    1908                 :  * HISTORY
    1909                 :  *   4/2003 Arthur Taylor (MDL/RSIS): Created
    1910                 :  *   6/2003 Matthew T. Kallio (matt@wunderground.com):
    1911                 :  *          "wmo" dimension increased to WMO_HEADER_LEN + 1 (for '\0' char)
    1912                 :  *
    1913                 :  * NOTES
    1914                 :  *****************************************************************************
    1915                 :  */
    1916                 : #ifdef DEBUG_DEGRIB1
    1917                 : int main (int argc, char **argv)
    1918                 : {
    1919                 :    DataSource grib_fp;       /* The opened grib2 file for input. */
    1920                 :    sInt4 offset;        /* Where we currently are in grib_fp. */
    1921                 :    sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
    1922                 :    char wmo[WMO_HEADER_LEN + 1]; /* Holds the current wmo message. */
    1923                 :    sInt4 gribLen;       /* Length of the current GRIB message. */
    1924                 :    sInt4 wmoLen;        /* Length of current wmo Message. */
    1925                 :    char *msg;
    1926                 :    int version;
    1927                 :    sChar f_unit = 0;
    1928                 :    double *grib_Data;
    1929                 :    sInt4 grib_DataLen;
    1930                 :    grib_MetaData meta;
    1931                 :    IS_dataType is;      /* Un-parsed meta data for this GRIB2 message. As
    1932                 :                          * well as some memory used by the unpacker. */
    1933                 : 
    1934                 :    //if ((grib_fp = fopen (argv[1], "rb")) == NULL) {
    1935                 :    //   printf ("Problems opening %s for read\n", argv[1]);
    1936                 :    //   return 1;
    1937                 :    //}
    1938                 :    grib_fp = FileDataSource(argv[1]);
    1939                 :    IS_Init (&is);
    1940                 :    MetaInit (&meta);
    1941                 : 
    1942                 :    offset = 0;
    1943                 :    if (ReadSECT0 (grib_fp, offset, WMO_HEADER_LEN, WMO_SECOND_LEN, wmo,
    1944                 :                   sect0, &gribLen, &wmoLen, &version) < 0) {
    1945                 :       msg = errSprintf (NULL);
    1946                 :       printf ("%s\n", msg);
    1947                 :       return -1;
    1948                 :    }
    1949                 :    grib_DataLen = 0;
    1950                 :    grib_Data = NULL;
    1951                 :    if (version == 1) {
    1952                 :       meta.GribVersion = version;
    1953                 :       ReadGrib1Record (grib_fp, f_unit, &grib_Data, &grib_DataLen, &meta,
    1954                 :                        &is, sect0, gribLen);
    1955                 :       offset = offset + gribLen + wmoLen;
    1956                 :    }
    1957                 : 
    1958                 :    MetaFree (&meta);
    1959                 :    IS_Free (&is);
    1960                 :    free (grib_Data);
    1961                 :    //fclose (grib_fp);
    1962                 :    return 0;
    1963                 : }
    1964                 : #endif

Generated by: LCOV version 1.7