LCOV - code coverage report
Current view: top level - frmts/grib/degrib/degrib - degrib1.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 455 899 50.6 %
Date: 2024-04-27 17:22:41 Functions: 10 11 90.9 %

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

Generated by: LCOV version 1.14