LCOV - code coverage report
Current view: top level - frmts/grib/degrib/degrib - grib2api.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 221 468 47.2 %
Date: 2024-04-27 17:22:41 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*****************************************************************************
       2             :  * grib2api.c
       3             :  *
       4             :  * DESCRIPTION
       5             :  *    This file contains the API to the GRIB2 libraries which is as close as
       6             :  * possible to the "official" NWS GRIB2 Library's API.  The reason for this
       7             :  * is so we can use NCEP's unofficial GRIB2 library while having minimal
       8             :  * impact on the already written drivers.
       9             :  *
      10             :  * HISTORY
      11             :  *  12/2003 Arthur Taylor (MDL / RSIS): Created.
      12             :  *
      13             :  * NOTES
      14             :  *****************************************************************************
      15             :  */
      16             : #include <limits.h>
      17             : #include <math.h>
      18             : #include <stdlib.h>
      19             : #include <string.h>
      20             : #include "grib2api.h"
      21             : #include "grib2.h"
      22             : #include "scan.h"
      23             : #include "tendian.h"
      24             : #include "myassert.h"
      25             : #include "gridtemplates.h"
      26             : #include "pdstemplates.h"
      27             : #include "drstemplates.h"
      28             : 
      29             : #include "cpl_port.h"
      30             : 
      31             : /* Commented out by GDAL: we can actually include gribtemplates.h */
      32             : #if 0
      33             : 
      34             : /* Would prefer to include "gribtemplates.h" but can't since NCEP decided to
      35             :  * put a const struct in it.  The result is if I include it, I get 2 copies
      36             :  * of the data.
      37             :  */
      38             : extern sInt4 getgridindex(sInt4 number);
      39             : 
      40             : /* have now put this in grib2api.h... may bring it back. */
      41             : #define MAXGRIDTEMP 23  /* maximum number of templates */
      42             : #define MAXGRIDMAPLEN 200 /* maximum template map length */
      43             : struct gridtemplate {
      44             :    sInt4 template_num;
      45             :    sInt4 mapgridlen;
      46             :    sInt4 needext;
      47             :    sInt4 mapgrid[MAXGRIDMAPLEN];
      48             : };
      49             : extern const struct gridtemplate templatesgrid[MAXGRIDTEMP];
      50             : 
      51             : /* Would prefer to include "pdstemplates.h" but can't since NCEP decided to
      52             :  * put a const struct in it.  The result is if I include it, I get 2 copies
      53             :  * of the data.
      54             :  */
      55             : extern sInt4 getpdsindex(sInt4 number);
      56             : 
      57             : /* have now put this in grib2api.h... may bring it back. */
      58             : #define MAXPDSTEMP 23   /* maximum number of templates */
      59             : #define MAXPDSMAPLEN 200 /* maximum template map length */
      60             : struct pdstemplate {
      61             :    sInt4 template_num;
      62             :    sInt4 mappdslen;
      63             :    sInt4 needext;
      64             :    sInt4 mappds[MAXPDSMAPLEN];
      65             : };
      66             : extern const struct pdstemplate templatespds[MAXPDSTEMP];
      67             : 
      68             : /* Would prefer to include "drstemplates.h" but can't since NCEP decided to
      69             :  * put a const struct in it.  The result is if I include it, I get 2 copies
      70             :  * of the data.
      71             :  */
      72             : extern sInt4 getdrsindex(sInt4 number);
      73             : 
      74             : #define MAXDRSTEMP 8    /* maximum number of templates */
      75             : #define MAXDRSMAPLEN 200 /* maximum template map length */
      76             : struct drstemplate {
      77             :    sInt4 template_num;
      78             :    sInt4 mapdrslen;
      79             :    sInt4 needext;
      80             :    sInt4 mapdrs[MAXDRSMAPLEN];
      81             : };
      82             : extern const struct drstemplate templatesdrs[MAXDRSTEMP];
      83             : #endif
      84             : 
      85      546952 : static sInt4 FloatToSInt4Clamp(float val) {
      86      546952 :    if ((double)val >= (double)INT_MAX) return INT_MAX;
      87      546952 :    if ((double)val <= (double)INT_MIN) return INT_MIN;
      88      546943 :    if (CPLIsNan(val)) return 0;
      89      546914 :    return (sInt4)val;
      90             : }
      91             : 
      92             : /*****************************************************************************
      93             :  * mdl_LocalUnpack() --
      94             :  *
      95             :  * Arthur Taylor / MDL
      96             :  *
      97             :  * PURPOSE
      98             :  *   Unpack the local use data assuming that it was packed using the MDL
      99             :  * encoder.  This assumes "local" starts at octet 6 (i.e. skipping over the
     100             :  * length and section ID octets)
     101             :  *
     102             :  *   In Section 2, GRIB2 provides for local use data.  The MDL encoder packs
     103             :  * that data, and signifies that it has done so by setting octet 6 to 1.
     104             :  * This may have been inadvisable, since the GRIB2 specs did not state that
     105             :  * octet 6 was special.
     106             :  *
     107             :  * ARGUMENTS
     108             :  *    local = The section 2 data prior to being unpacked. (Input)
     109             :  * locallen = The length of "local" (Input)
     110             :  *     idat = Unpacked MDL local data (if it was an integer) (Output)
     111             :  *    nidat = length of idat. (Input)
     112             :  *     rdat = Unpacked MDL local data (if it was a float) (Output)
     113             :  *    nrdat = length of rdat. (Input)
     114             :  *
     115             :  * FILES/DATABASES: None
     116             :  *
     117             :  * RETURNS: int
     118             :  *  0 = Ok.
     119             :  *  1 = Mixed local data types?
     120             :  *  2 = nrdat is not large enough.
     121             :  *  3 = nidat is not large enough.
     122             :  *  4 = Too many bits to unpack, should be a max of 32 bits.
     123             :  *  5 = Locallen is too small
     124             :  *
     125             :  * HISTORY
     126             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     127             :  *
     128             :  * NOTES
     129             :  *****************************************************************************
     130             :  */
     131             : #define GRIB_UNSIGN_INT2(a,b) ((a<<8)+b)
     132           0 : static int mdl_LocalUnpack(unsigned char *local, sInt4 locallen,
     133             :                            sInt4 *idat, sInt4 *nidat, float *rdat,
     134             :                            sInt4 *nrdat)
     135             : {
     136           0 :    int BytesUsed = 0;   /* How many bytes have been used. */
     137             :    unsigned int numGroup; /* Number of groups */
     138             :    int i;               /* Counter over the groups. */
     139             :    sInt4 numVal;        /* Number of values in a given group. */
     140             :    float refVal;        /* The reference value in a given group. */
     141             :    unsigned int scale;  /* The power of 10 scale value in the group. */
     142             :    sInt4 recScale10;    /* 1 / 10**scale.. For faster computations. */
     143             :    unsigned char numBits; /* # of bits for a single element in the group. */
     144             :    char f_dataType;     /* If the local data is a float or integer. */
     145           0 :    char f_firstType = 0; /* The type of the first group of local data. */
     146           0 :    int curIndex = 0;    /* Where to store the current data. */
     147             :    int j;               /* Counter over the number of values in a group. */
     148             :    size_t numUsed;      /* Number of bytes used in call to memBitRead. */
     149             :    uChar bufLoc;        /* Where to read for more bits in the data stream. */
     150             :    uInt4 uli_temp;      /* Temporary storage to hold unpacked data. */
     151             : 
     152           0 :    if (locallen < BytesUsed + 3) {
     153             : #ifdef DEBUG
     154           0 :       printf("Locallen is too small.\n");
     155             : #endif
     156           0 :       return 5;
     157             :    }
     158             :    /* The calling routine should check octet 6, which is local[0], to be 1,
     159             :     * so we just assert it is 1. */
     160           0 :    myAssert(local[0] == 1);
     161           0 :    numGroup = GRIB_UNSIGN_INT2(local[1], local[2]);
     162           0 :    local += 3;
     163           0 :    BytesUsed += 3;
     164           0 :    myAssert(*nrdat > 1);
     165           0 :    myAssert(*nidat > 1);
     166           0 :    idat[0] = 0;
     167           0 :    rdat[0] = 0;
     168             : 
     169           0 :    for (i = 0; (unsigned int)i < numGroup; i++) {
     170           0 :       if (locallen < BytesUsed + 12) {
     171             : #ifdef DEBUG
     172           0 :          printf("Locallen is too small.\n");
     173             : #endif
     174           0 :          return 5;
     175             :       }
     176           0 :       MEMCPY_BIG(&numVal, local, sizeof (sInt4));
     177           0 :       MEMCPY_BIG(&refVal, local + 4, sizeof (float));
     178           0 :       scale = GRIB_UNSIGN_INT2(local[8], local[9]);
     179           0 :       recScale10 = (sInt4)(1 / pow (10.0, scale));
     180           0 :       numBits = local[10];
     181           0 :       if (numBits >= 32) {
     182             : #ifdef DEBUG
     183           0 :          printf("Too many bits too unpack.\n");
     184             : #endif
     185           0 :          return 4;
     186             :       }
     187           0 :       f_dataType = local[11];
     188           0 :       local += 12;
     189           0 :       BytesUsed += 12;
     190           0 :       if (locallen < BytesUsed + ((numBits * numVal) + 7) / 8) {
     191             : #ifdef DEBUG
     192           0 :          printf("Locallen is too small.\n");
     193             : #endif
     194           0 :          return 5;
     195             :       }
     196           0 :       if (i == 0) {
     197           0 :          f_firstType = f_dataType;
     198           0 :       } else if (f_firstType != f_dataType) {
     199             : #ifdef DEBUG
     200           0 :          printf("Local use data has mixed float/integer type?\n");
     201             : #endif
     202           0 :          return 1;
     203             :       }
     204           0 :       bufLoc = 8;
     205           0 :       if (f_dataType == 0) {
     206             :          /* Floating point data. */
     207           0 :          if (*nrdat < (curIndex + numVal + 3)) {
     208             : #ifdef DEBUG
     209           0 :             printf("nrdat is not large enough.\n");
     210             : #endif
     211           0 :             return 2;
     212             :          }
     213           0 :          rdat[curIndex] = numVal;
     214           0 :          curIndex++;
     215           0 :          rdat[curIndex] = scale;
     216           0 :          curIndex++;
     217           0 :          for (j = 0; j < numVal; j++) {
     218           0 :             memBitRead(&uli_temp, sizeof(sInt4), local, numBits,
     219             :                        &bufLoc, &numUsed);
     220           0 :             local += numUsed;
     221           0 :             BytesUsed += (int) numUsed;
     222           0 :             rdat[curIndex] = (refVal + uli_temp) * recScale10;
     223           0 :             curIndex++;
     224             :          }
     225           0 :          rdat[curIndex] = 0;
     226             :       } else {
     227             :          /* Integer point data. */
     228           0 :          if (*nidat < (curIndex + numVal + 3)) {
     229             : #ifdef DEBUG
     230           0 :             printf("nidat is not large enough.\n");
     231             : #endif
     232           0 :             return 3;
     233             :          }
     234           0 :          idat[curIndex] = numVal;
     235           0 :          curIndex++;
     236           0 :          idat[curIndex] = scale;
     237           0 :          curIndex++;
     238           0 :          for (j = 0; j < numVal; j++) {
     239           0 :             memBitRead(&uli_temp, sizeof(sInt4), local, numBits,
     240             :                        &bufLoc, &numUsed);
     241           0 :             local += numUsed;
     242           0 :             BytesUsed += (int) numUsed;
     243           0 :             idat[curIndex] = (sInt4)((refVal + uli_temp) * recScale10);
     244           0 :             curIndex++;
     245             :          }
     246           0 :          idat[curIndex] = 0;
     247             :       }
     248             :    }
     249           0 :    return 0;
     250             : }
     251             : 
     252             : /*****************************************************************************
     253             :  * fillOutSectLen() --
     254             :  *
     255             :  * Arthur Taylor / MDL
     256             :  *
     257             :  * PURPOSE
     258             :  *   The GRIB2 API returns the lengths of each GRIB2 section along with the
     259             :  * meta data.  NCEP's routines did not, so this routine fills in that part.
     260             :  * This routine has to consider which grid is being unpacked.
     261             :  *
     262             :  *   c_ipack is passed in after section 1 (since section 1 is not repeated)
     263             :  *
     264             :  * ARGUMENTS
     265             :  *  c_ipack = Complete GRIB2 message to look for the section lengths in. (In)
     266             :  * lenCpack = Length of c_ipack (Input)
     267             :  *  subgNum = Which sub rid to find the section lengths of. (Input)
     268             :  *      is2 = Section 2 data (Output)
     269             :  *      is3 = Section 3 data (Output)
     270             :  *      is4 = Section 4 data (Output)
     271             :  *      is5 = Section 5 data (Output)
     272             :  *      is6 = Section 6 data (Output)
     273             :  *      is7 = Section 7 data (Output)
     274             :  *
     275             :  * FILES/DATABASES: None
     276             :  *
     277             :  * RETURNS: int
     278             :  *  0 = Ok.
     279             :  *  1 = c_ipack is not large enough
     280             :  *  2 = invalid section number
     281             :  *
     282             :  * HISTORY
     283             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     284             :  *
     285             :  * NOTES
     286             :  *****************************************************************************
     287             :  */
     288         460 : static int fillOutSectLen(unsigned char *c_ipack, int lenCpack,
     289             :                           int subgNum, sInt4 *is2, sInt4 *is3,
     290             :                           sInt4 *is4, sInt4 *is5, sInt4 *is6, sInt4 *is7)
     291             : {
     292         460 :    sInt4 offset = 0;    /* How far in c_ipack we have read. */
     293             :    sInt4 sectLen;       /* The length of the current section. */
     294             :    int sectId;          /* The current section number. */
     295         460 :    unsigned int gNum = 0; /* Which sub group we are currently working with. */
     296             : 
     297         460 :    if (lenCpack < 5) {
     298             : #ifdef DEBUG
     299           0 :       printf("Cpack is not large enough.\n");
     300             : #endif
     301           0 :       return 1;
     302             :    }
     303             :    /* assert that we start with data in either section 2 or 3. */
     304         460 :    myAssert((c_ipack[4] == 2) || (c_ipack[4] == 3));
     305        3196 :    while (gNum <= (unsigned int)subgNum) {
     306        2736 :       if (lenCpack < offset + 5) {
     307             : #ifdef DEBUG
     308           0 :          printf("Cpack is not large enough.\n");
     309             : #endif
     310           0 :          return 1;
     311             :       }
     312        2736 :       MEMCPY_BIG(&sectLen, c_ipack + offset, sizeof(sInt4));
     313             :       /* Check if we just read section 8.  If so, then it is "7777" =
     314             :        * 926365495 regardless of endian'ness. */
     315        2736 :       if (sectLen == 926365495L) {
     316             : #ifdef DEBUG
     317           0 :          printf("Shouldn't see sect 8. Should stop after correct sect 7\n");
     318             : #endif
     319           0 :          return 2;
     320             :       }
     321        2736 :       sectId = c_ipack[offset + 4];
     322        2736 :       switch (sectId) {
     323         424 :          case 2:
     324         424 :             is2[0] = sectLen;
     325         424 :             break;
     326         460 :          case 3:
     327         460 :             is3[0] = sectLen;
     328         460 :             break;
     329         463 :          case 4:
     330         463 :             is4[0] = sectLen;
     331         463 :             break;
     332         463 :          case 5:
     333         463 :             is5[0] = sectLen;
     334         463 :             break;
     335         463 :          case 6:
     336         463 :             is6[0] = sectLen;
     337         463 :             break;
     338         463 :          case 7:
     339         463 :             is7[0] = sectLen;
     340         463 :             gNum++;
     341         463 :             break;
     342           0 :          default:
     343             : #ifdef DEBUG
     344           0 :             printf("Invalid section id %d.\n", sectId);
     345             : #endif
     346           0 :             return 2;
     347             :       }
     348        2736 :       offset += sectLen;
     349             :    }
     350         460 :    return 0;
     351             : }
     352             : 
     353             : /*****************************************************************************
     354             :  * TransferInt() --
     355             :  *
     356             :  * Arthur Taylor / MDL
     357             :  *
     358             :  * PURPOSE
     359             :  *   To transfer the data from "fld" and "bmap" to "iain" and "ib".  The API
     360             :  * attempts to rearrange the order, so that anything returned from it has
     361             :  * scan mode 0100????
     362             :  *
     363             :  * ARGUMENTS
     364             :  *          fld = The expanded grid from NCEPs routines (Input)
     365             :  *      ngrdpts = Length of fld (Input)
     366             :  *      ibitmap = flag if we have a bitmap or not. (Input)
     367             :  *         bmap = bitmap from NCEPs routines. (Input)
     368             :  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
     369             :  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
     370             :  *       nx, ny = The dimensions of the grid. (Input)
     371             :  *       iclean = 1 means the user wants the unpacked data returned without
     372             :  *                missing values in it. 0 means embed the missing values. (In)
     373             :  *       xmissp = The primary missing value to use if iclean = 0. (Input).
     374             :  *         iain = The grid to return. (Output)
     375             :  *        nd2x3 = The length of iain. (Input)
     376             :  *           ib = Bitmap if it was packed (Output)
     377             :  *
     378             :  * FILES/DATABASES: None
     379             :  *
     380             :  * RETURNS: int
     381             :  *  0 = Ok.
     382             :  *  1 = nd2x3 is too small.
     383             :  *  2 = nx*ny != ngrdpts
     384             :  *
     385             :  * HISTORY
     386             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     387             :  *
     388             :  * NOTES
     389             :  *   May want to disable the scan adjustment in the future.
     390             :  *****************************************************************************
     391             :  */
     392          67 : static int TransferInt(float *fld, sInt4 ngrdpts, sInt4 ibitmap,
     393             :                        sInt4 *bmap, char f_ignoreScan, sInt4 *scan,
     394             :                        sInt4 nx, sInt4 ny, sInt4 iclean, float xmissp,
     395             :                        sInt4 *iain, sInt4 nd2x3, sInt4 *ib)
     396             : {
     397             :    int i;               /* loop counter over all grid points. */
     398             :    sInt4 x, y;          /* Where we are in a grid of scan value 0100???? */
     399             :    int curIndex;        /* Where in iain to store the current data. */
     400             : 
     401          67 :    if (nd2x3 < ngrdpts) {
     402             : #ifdef DEBUG
     403           0 :       printf("nd2x3(%d) is < ngrdpts(%d)\n", nd2x3, ngrdpts);
     404             : #endif
     405           0 :       return 1;
     406             :    }
     407          67 :    if (f_ignoreScan || ((*scan & 0xf0) == 64)) {
     408          67 :       if (ibitmap) {
     409           0 :          for (i = 0; i < ngrdpts; i++) {
     410           0 :             ib[i] = bmap[i];
     411             :             /* Check if we are supposed to insert xmissp into the field */
     412           0 :             if ((iclean != 0) && (ib[i] == 0)) {
     413           0 :                iain[i] = FloatToSInt4Clamp(xmissp);
     414             :             } else {
     415           0 :                iain[i] = FloatToSInt4Clamp(fld[i]);
     416             :             }
     417             :          }
     418             :       } else {
     419      546457 :          for (i = 0; i < ngrdpts; i++) {
     420      546390 :             iain[i] = FloatToSInt4Clamp(fld[i]);
     421             :          }
     422             :       }
     423             :    } else {
     424           0 :       if( nx <= 0 || ny <= 0 )
     425             :       {
     426           0 :           return 1;
     427             :       }
     428           0 :       if (ny != ngrdpts / nx) {
     429             : #ifdef DEBUG
     430           0 :          printf("nx(%d) * ny(%d) != ngrdpts(%d)\n", nx, ny, ngrdpts);
     431             : #endif
     432           0 :          return 2;
     433             :       }
     434           0 :       if (ibitmap) {
     435           0 :          for (i = 0; i < ngrdpts; i++) {
     436           0 :             ScanIndex2XY(i, &x, &y, *scan, nx, ny);
     437             :             /* ScanIndex returns value as if scan was 0100(0000) */
     438           0 :             curIndex = (x - 1) + (y - 1) * nx;
     439           0 :             if( curIndex < 0 || curIndex >= nd2x3 )
     440           0 :                 return 1;
     441           0 :             ib[curIndex] = bmap[i];
     442             :             /* Check if we are supposed to insert xmissp into the field */
     443           0 :             if ((iclean != 0) && (ib[curIndex] == 0)) {
     444           0 :                iain[i] = FloatToSInt4Clamp(xmissp);
     445             :             } else {
     446           0 :                iain[curIndex] = FloatToSInt4Clamp(fld[i]);
     447             :             }
     448             :          }
     449             :       } else {
     450           0 :          for (i = 0; i < ngrdpts; i++) {
     451           0 :             ScanIndex2XY (i, &x, &y, *scan, nx, ny);
     452             :             /* ScanIndex returns value as if scan was 0100(0000) */
     453           0 :             curIndex = (x - 1) + (y - 1) * nx;
     454           0 :             if( curIndex < 0 || curIndex >= nd2x3 )
     455           0 :                 return 1;
     456           0 :             iain[curIndex] = FloatToSInt4Clamp(fld[i]);
     457             :          }
     458             :       }
     459           0 :       *scan = 64 + (*scan & 0x0f);
     460             :    }
     461          67 :    return 0;
     462             : }
     463             : 
     464             : /*****************************************************************************
     465             :  * TransferFloat() --
     466             :  *
     467             :  * Arthur Taylor / MDL
     468             :  *
     469             :  * PURPOSE
     470             :  *   To transfer the data from "fld" and "bmap" to "ain" and "ib".  The API
     471             :  * attempts to rearrange the order, so that anything returned from it has
     472             :  * scan mode 0100????
     473             :  *
     474             :  * ARGUMENTS
     475             :  *          fld = The expanded grid from NCEPs routines (Input)
     476             :  *      ngrdpts = Length of fld (Input)
     477             :  *      ibitmap = flag if we have a bitmap or not. (Input)
     478             :  *         bmap = bitmap from NCEPs routines. (Input)
     479             :  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
     480             :  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
     481             :  *       nx, ny = The dimensions of the grid. (Input)
     482             :  *       iclean = 1 means the user wants the unpacked data returned without
     483             :  *                missing values in it. 0 means embed the missing values. (In)
     484             :  *       xmissp = The primary missing value to use if iclean = 0. (Input).
     485             :  *          ain = The grid to return. (Output)
     486             :  *        nd2x3 = The length of iain. (Input)
     487             :  *           ib = Bitmap if it was packed (Output)
     488             :  *
     489             :  * FILES/DATABASES: None
     490             :  *
     491             :  * RETURNS: int
     492             :  *  0 = Ok.
     493             :  *  1 = nd2x3 is too small.
     494             :  *  2 = nx*ny != ngrdpts
     495             :  *
     496             :  * HISTORY
     497             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     498             :  *
     499             :  * NOTES
     500             :  *   May want to disable the scan adjustment in the future.
     501             :  *****************************************************************************
     502             :  */
     503          90 : static int TransferFloat(float *fld, sInt4 ngrdpts, sInt4 ibitmap,
     504             :                          sInt4 *bmap, char f_ignoreScan, sInt4 *scan,
     505             :                          sInt4 nx, sInt4 ny, sInt4 iclean, float xmissp,
     506             :                          float *ain, sInt4 nd2x3, sInt4 *ib)
     507             : {
     508             :    int i;               /* loop counter over all grid points. */
     509             :    sInt4 x, y;          /* Where we are in a grid of scan value 0100???? */
     510             :    uInt4 curIndex;      /* Where in ain to store the current data. */
     511             : 
     512          90 :    if (nd2x3 < ngrdpts) {
     513             : #ifdef DEBUG
     514           0 :       printf("nd2x3(%d) is < ngrdpts(%d)\n", nd2x3, ngrdpts);
     515             : #endif
     516           0 :       return 1;
     517             :    }
     518          90 :    if (f_ignoreScan || ((*scan & 0xf0) == 64)) {
     519          76 :     if( ain ) {
     520          76 :       if (ibitmap) {
     521         802 :          for (i = 0; i < ngrdpts; i++) {
     522         800 :             ib[i] = bmap[i];
     523             :             /* Check if we are supposed to insert xmissp into the field */
     524         800 :             if ((iclean != 0) && (ib[i] == 0)) {
     525           0 :                ain[i] = xmissp;
     526             :             } else {
     527         800 :                ain[i] = fld[i];
     528             :             }
     529             :          }
     530             :       } else {
     531     2216200 :          for (i = 0; i < ngrdpts; i++) {
     532     2216130 :             ain[i] = fld[i];
     533             :          }
     534             :       }
     535             :     }
     536             :    } else {
     537          14 :       if( nx <= 0 || ny <= 0 )
     538             :       {
     539           0 :           return 1;
     540             :       }
     541          14 :       if (ny != ngrdpts / nx) {
     542             : #ifdef DEBUG
     543           0 :          printf("nx(%d) * ny(%d) != ngrdpts(%d)\n", nx, ny, ngrdpts);
     544             : #endif
     545           0 :          return 2;
     546             :       }
     547          14 :       if (ibitmap) {
     548           0 :          for (i = 0; i < ngrdpts; i++) {
     549           0 :             ScanIndex2XY(i, &x, &y, *scan, nx, ny);
     550           0 :             if (x <= 0 || y <= 0 )
     551           0 :                 return 1;
     552             :             /* ScanIndex returns value as if scan was 0100(0000) */
     553           0 :             curIndex = (uInt4)(x - 1) + (uInt4)(y - 1) * (uInt4)nx;
     554           0 :             if (curIndex >= (uInt4)nd2x3)
     555           0 :                 return 1;
     556           0 :             ib[curIndex] = bmap[i];
     557           0 :             if( ain )
     558             :             {
     559             :                 /* Check if we are supposed to insert xmissp into the field */
     560           0 :                 if ((iclean != 0) && (ib[curIndex] == 0)) {
     561           0 :                 ain[i] = xmissp;
     562             :                 } else {
     563           0 :                 ain[curIndex] = fld[i];
     564             :                 }
     565             :             }
     566             :          }
     567             :       } else {
     568     5408080 :          for (i = 0; i < ngrdpts; i++) {
     569     5408060 :             ScanIndex2XY(i, &x, &y, *scan, nx, ny);
     570     5408060 :             if (x <= 0 || y <= 0 )
     571           0 :                 return 1;
     572             :             /* ScanIndex returns value as if scan was 0100(0000) */
     573     5408060 :             curIndex = (uInt4)(x - 1) + (uInt4)(y - 1) * (uInt4)nx;
     574     5408060 :             if( curIndex >= (uInt4)nd2x3 )
     575           0 :                 return 1;
     576     5408060 :             if( ain )
     577     5408060 :                 ain[curIndex] = fld[i];
     578             :          }
     579             :       }
     580          14 :       *scan = 64 + (*scan & 0x0f);
     581             :    }
     582             : /*
     583             :    if (1==1) {
     584             :       int i;
     585             :       for (i=0; i < ngrdpts; i++) {
     586             :          if (ain[i] != 9999) {
     587             :             fprintf (stderr, "grib2api.c: ain[%d] %f, fld[%d] %f\n", i, ain[i],
     588             :                      i, fld[i]);
     589             :          }
     590             :       }
     591             :    }
     592             : */
     593          90 :    return 0;
     594             : }
     595             : 
     596             : #ifdef PKNCEP
     597             : int pk_g2ncep(sInt4 *kfildo, float *ain, sInt4 *iain, sInt4 *nx,
     598             :               sInt4 *ny, sInt4 *idat, sInt4 *nidat, float *rdat,
     599             :               sInt4 *nrdat, sInt4 *is0, sInt4 *ns0, sInt4 *is1,
     600             :               sInt4 *ns1, sInt4 *is3, sInt4 *ns3, sInt4 *is4,
     601             :               sInt4 *ns4, sInt4 *is5, sInt4 *ns5, sInt4 *is6,
     602             :               sInt4 *ns6, sInt4 *is7, sInt4 *ns7, sInt4 *ib,
     603             :               sInt4 *ibitmap, unsigned char *cgrib, sInt4 *nd5,
     604             :               sInt4 *missp, float *xmissp, sInt4 *misss,
     605             :               float *xmisss, sInt4 *inew, sInt4 *minpk, sInt4 *iclean,
     606             :               sInt4 *l3264b, sInt4 *jer, sInt4 *ndjer, sInt4 *kjer)
     607             : {
     608             :    g2int listsec0[2];
     609             :    g2int listsec1[13];
     610             :    g2int igds[5];
     611             :    g2int igdstmpl[];
     612             :    int ierr;            /* Holds the error code from a called routine. */
     613             :    int i;
     614             : 
     615             :    listsec0[0] = is0[6];
     616             :    listsec0[1] = is0[7];
     617             : 
     618             :    listsec1[0] = is1[5];
     619             :    listsec1[1] = is1[7];
     620             :    listsec1[2] = is1[9];
     621             :    listsec1[3] = is1[10];
     622             :    listsec1[4] = is1[11];
     623             :    listsec1[5] = is1[12];
     624             :    listsec1[6] = is1[14];
     625             :    listsec1[7] = is1[15];
     626             :    listsec1[8] = is1[16];
     627             :    listsec1[9] = is1[17];
     628             :    listsec1[10] = is1[18];
     629             :    listsec1[11] = is1[19];
     630             :    listsec1[12] = is1[20];
     631             : 
     632             :    ierr = g2_create(cgrib, listsec0, listsec1);
     633             :    printf("Length = %d\n", ierr);
     634             : 
     635             :    if ((idat[0] != 0) || (rdat[0] != 0)) {
     636             :       printf("Don't handle this yet.\n");
     637             : /*
     638             :       ierr = g2_addlocal (cgrib, unsigned char *csec2, g2int lcsec2);
     639             : */
     640             :    }
     641             : 
     642             :    igds[0] = is3[5];
     643             :    igds[1] = is3[6];
     644             :    igds[2] = is3[10];
     645             :    igds[3] = is3[11];
     646             :    igds[4] = is3[12];
     647             : 
     648             :    IS3(15) - IS3(nn) = Grid Definition Template, stored in bytes 15 - nn(*)
     649             : 
     650             :          ierr = g2_addgrid(cgrib, igds, g2int * igdstmpl, g2int * ideflist,
     651             :                            g2int idefnum)
     652             : 
     653             : 
     654             : 
     655             : 
     656             :    return 0;
     657             : /*
     658             : 
     659             : To start a new GRIB2 message, call function g2_create.  G2_create
     660             : encodes Sections 0 and 1 at the beginning of the message.  This routine
     661             : must be used to create each message.
     662             : 
     663             : Routine g2_addlocal can be used to add a Local Use Section ( Section 2 ).
     664             : Note that this section is optional and need not appear in a GRIB2 message.
     665             : 
     666             : Function g2_addgrid is used to encode a grid definition into Section 3.
     667             : This grid definition defines the geometry of the data values in the
     668             : fields that follow it.  g2_addgrid can be called again to change the grid
     669             : definition describing subsequent data fields.
     670             : 
     671             : Each data field is added to the GRIB2 message using routine g2_addfield,
     672             : which adds Sections 4, 5, 6, and 7 to the message.
     673             : 
     674             : After all desired data fields have been added to the GRIB2 message, a
     675             : call to function g2_gribend is needed to add the final section 8 to the
     676             : message and to update the length of the message.  A call to g2_gribend
     677             : is required for each GRIB2 message.
     678             : */
     679             : 
     680             : }
     681             : #endif
     682             : 
     683             : /*****************************************************************************
     684             :  * unpk_g2ncep() --
     685             :  *
     686             :  * Arthur Taylor / MDL
     687             :  *
     688             :  * PURPOSE
     689             :  *   This procedure is a wrapper around the NCEP GRIB2 routines to interface
     690             :  * their routines with the "official NWS" GRIB2 API.  The reason for this is
     691             :  * so drivers that have been written to use the "official NWS" GRIB2 API, can
     692             :  * use the NCEP library with minimal disruption.
     693             :  *
     694             :  * ARGUMENTS
     695             :  *  kfildo = Unit number for output diagnostics (C ignores this). (Input)
     696             :  *     ain = contains the data if the original data was float data.
     697             :  *           (size = nd2x3) (Output)
     698             :  *    iain = contains the data if the original data was integer data.
     699             :  *           (size = nd2x3) (Output)
     700             :  *   nd2x3 = length of ain, iain, ib (Input)
     701             :  *           (at least the size of num grid points)
     702             :  *    idat = local use data if any that were unpacked from Section 2. (Output)
     703             :  *   nidat = length of idat. (Input)
     704             :  *    rdat = floating point local use data (Output)
     705             :  *   nrdat = length of rdat. (Input)
     706             :  *     is0 = Section 0 data (Output)
     707             :  *     ns0 = length of is0 (16 is fine) (Input)
     708             :  *     is1 = Section 1 data (Output)
     709             :  *     ns1 = length of is1 (21 is fine) (Input)
     710             :  *     is2 = Section 2 data (Output)
     711             :  *     ns2 = length of is2 () (Input)
     712             :  *     is3 = Section 3 data (Output)
     713             :  *     ns3 = length of is3 (96 or 1600) (Input)
     714             :  *     is4 = Section 4 data (Output)
     715             :  *     ns4 = length of is4 (60) (Input)
     716             :  *     is5 = Section 5 data (Output)
     717             :  *     ns5 = length of is5 (49 is fine) (Input)
     718             :  *     is6 = Section 6 data (Output)
     719             :  *     ns6 = length of is6 (6 is fine) (Input)
     720             :  *     is7 = Section 7 data (Output)
     721             :  *     ns7 = length of is7 (8 is fine) (Input)
     722             :  *      ib = Bitmap if user requested it, and it was packed (Output)
     723             :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Output)
     724             :  * c_ipack = The message to unpack (Input)
     725             :  *     nd5 = 1/4 the size of c_ipack (Input)
     726             :  *  xmissp = The floating point representation for the primary missing value.
     727             :  *           (Input/Output)
     728             :  *  xmisss = The floating point representation for the secondary missing
     729             :  *           value (Input/Output)
     730             :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
     731             :  *  iclean = 1 means the user wants the unpacked data returned without
     732             :  *           missing values in it. 0 means embed the missing values. (Input)
     733             :  *  l3264b = Integer word length in bits (32 or 64) (Input)
     734             :  *  iendpk = A 1 means no more grids in this message, a 0 means more grids.
     735             :  *           (Output)
     736             :  * jer(ndjer,2) = error codes along with severity. (Output)
     737             :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
     738             :  *    kjer = number of error messages stored in jer.
     739             :  *
     740             :  * FILES/DATABASES: None
     741             :  *
     742             :  * RETURNS: void
     743             :  *   "jer" is used to store error messages, and kjer is used to denote how
     744             :  * many there were.  Jer is set up as a 2 column array, with the first
     745             :  * column in the first half of the array, and denoting the GRIB2 section
     746             :  * an error occurred in.  The second column denoting the severity.
     747             :  *
     748             :  *    The possibilities from unpk_g2ncep() are as follows:
     749             :  * ker=1 jer[0,0]=0    jer[0,1]=2: Message is not formed correctly
     750             :  *                                 Request for an invalid subgrid
     751             :  *                                 Problems unpacking the data.
     752             :  *                                 problems expanding the data.
     753             :  *                                 Calling dimensions were too small.
     754             :  * ker=2 jer[1,0]=100  jer[1,1]=2: Error unpacking section 1.
     755             :  * ker=3 jer[2,0]=200  jer[2,1]=2: Error unpacking section 2.
     756             :  * ker=4 jer[3,0]=300  jer[3,1]=2: Error unpacking section 3.
     757             :  * ker=5 jer[4,0]=400  jer[4,1]=2: Error unpacking section 4.
     758             :  * ker=6 jer[5,0]=500  jer[5,1]=2: Error unpacking section 5.
     759             :  *                                 Data Template not implemented.
     760             :  *                                 During Transfer, nx * ny != ngrdpts.
     761             :  * ker=7 jer[6,0]=600  jer[6,1]=2: Error unpacking section 6.
     762             :  * ker=8 jer[7,0]=700  jer[7,1]=2: Error unpacking section 7.
     763             :  * ker=9 jer[8,0]=2001 jer[8,1]=2: nd2x3 is not large enough.
     764             :  * ker=9 jer[8,0]=2003 jer[8,1]=2: undefined sect 3 template
     765             :  *                                 (see gridtemplates.h).
     766             :  * ker=9 jer[8,0]=2004 jer[8,1]=2: undefined sect 4 template
     767             :  *                                 (see pdstemplates.h).
     768             :  * ker=9 jer[8,0]=2005 jer[8,1]=2: undefined sect 5 template
     769             :  *                                 (see drstemplates.h).
     770             :  * ker=9 jer[8,0]=9999 jer[8,1]=2: NCEP returns an unrecognized error.
     771             :  *
     772             :  * HISTORY
     773             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     774             :  *
     775             :  * NOTES
     776             :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
     777             :  * MDL attempts to always return grids in scan mode 0100????
     778             :  *
     779             :  * ToDo: Check length of parameters better.
     780             :  * ToDo: Probably shouldn't abort if they have problems expanding the data.
     781             :  * ToDo: Better handling of:
     782             :  * gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array contains
     783             :  *      the number of grid points contained in each row (or column). (part of
     784             :  *      Section 3)  This element is a pointer to an array that holds the data.
     785             :  *      This pointer is nullified if gfld->numoct_opt=0.
     786             :  * gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)  The number of entries in
     787             :  *      array ideflist.  i.e. number of rows (or columns) for which optional
     788             :  *      grid points are defined.  This value is set to zero, if
     789             :  *      gfld->numoct_opt=0.
     790             :  * gfld->coord_list  = Real array containing floating point values intended to
     791             :  *      document the vertical discretisation associated to model data on
     792             :  *      hybrid coordinate vertical levels.  (part of Section 4) This element
     793             :  *      is a pointer to an array that holds the data.
     794             :  * gfld->num_coord = number of values in array gfld->coord_list[].
     795             :  *****************************************************************************
     796             :  */
     797         460 : void unpk_g2ncep(CPL_UNUSED sInt4 *kfildo, float *ain, sInt4 *iain, sInt4 *nd2x3,
     798             :                  sInt4 *idat, sInt4 *nidat, float *rdat, sInt4 *nrdat,
     799             :                  sInt4 *is0, CPL_UNUSED sInt4 *ns0, sInt4 *is1, CPL_UNUSED sInt4 *ns1,
     800             :                  sInt4 *is2, sInt4 *ns2, sInt4 *is3, sInt4 *ns3,
     801             :                  sInt4 *is4, sInt4 *ns4, sInt4 *is5, CPL_UNUSED sInt4 *ns5,
     802             :                  sInt4 *is6, CPL_UNUSED sInt4 *ns6, sInt4 *is7, CPL_UNUSED sInt4 *ns7,
     803             :                  sInt4 *ib, sInt4 *ibitmap, unsigned char *c_ipack,
     804             :                  sInt4 *nd5, float *xmissp, float *xmisss,
     805             :                  sInt4 *inew, sInt4 *iclean, CPL_UNUSED sInt4 *l3264b,
     806             :                  sInt4 *iendpk, sInt4 *jer, sInt4 *ndjer, sInt4 *kjer)
     807             : {
     808             :    int i;               /* A counter used for a number of purposes. */
     809             :    static unsigned int subgNum = 0; /* The sub grid we read most recently.
     810             :                                      * This is primarily to help with the
     811             :                                      * inew option. */
     812             :    int ierr;            /* Holds the error code from a called routine. */
     813             :    sInt4 listsec0[3];
     814             :    sInt4 listsec1[13];
     815             :    static sInt4 numfields = 1; /* Number of sub Grids in this message */
     816             :    sInt4 numlocal;      /* Number of local sections in this message. */
     817             :    int unpack;          /* Tell g2_getfld to unpack the message. */
     818             :    int expand;          /* Tell g2_getflt to attempt to expand the bitmap. */
     819             :    gribfield *gfld;     /* Holds the data after g2_getfld unpacks it. */
     820             :    sInt4 gridIndex;     /* index in templatesgrid[] for this sect 3 templat */
     821             :    sInt4 pdsIndex;      /* index in templatespds[] for this sect 4 template */
     822             :    sInt4 drsIndex;      /* index in templatesdrs[] for this sect 5 template */
     823             :    int curIndex;        /* Where in is3, is4, or is5 to store meta data */
     824             :    int scanIndex;       /* Where in is3 to find the scan mode. */
     825             :    int nxIndex;         /* Where in is3 to find the number of x values. */
     826             :    int nyIndex;         /* Where in is3 to find the number of y values. */
     827             :    float f_temp;        /* Assist with handling weird MDL behavior in is5[] */
     828             :    char f_ignoreScan;   /* Flag to ignore the attempt at changing the scan */
     829             :    sInt4 dummyScan;     /* Dummy place holder for call to Transfer routines
     830             :                          * if ignoring scan. */
     831         460 :    const struct gridtemplate *templatesgrid = get_templatesgrid();
     832             : 
     833         460 :    myAssert(*ndjer >= 8);
     834             :    /* Init the error handling array. */
     835         460 :    memset((void *)jer, 0, 2 * *ndjer * sizeof(sInt4));
     836        4140 :    for (i = 0; i < 8; i++) {
     837        3680 :       jer[i] = i * 100;
     838             :    }
     839         460 :    *kjer = 8;
     840             : 
     841             :    /* The first time in, figure out how many grids there are, and store it in
     842             :     * numfields for subsequent calls with inew != 1. */
     843         460 :    if (*inew == 1) {
     844         457 :       subgNum = 0;
     845         457 :       ierr = g2_info(c_ipack, listsec0, listsec1, &numfields, &numlocal);
     846         457 :       if (ierr != 0) {
     847           0 :          switch (ierr) {
     848           0 :             case 1:    /* Beginning characters "GRIB" not found. */
     849             :             case 2:    /* GRIB message is not Edition 2. */
     850             :             case 3:    /* Could not find Section 1, where expected. */
     851             :             case 4:    /* End string "7777" found, but not where expected. */
     852             :             case 5:    /* End string "7777" not found at end of message. */
     853             :             case 6:    /* Invalid section number found. */
     854           0 :                jer[0 + *ndjer] = 2;
     855           0 :                *kjer = 1;
     856           0 :                break;
     857           0 :             default:
     858           0 :                jer[8 + *ndjer] = 2;
     859           0 :                jer[8] = 9999; /* Unknown error message. */
     860           0 :                *kjer = 9;
     861             :          }
     862         303 :          return;
     863             :       }
     864             :    } else {
     865           3 :       if (subgNum + 1 >= (unsigned int)numfields) {
     866             :          /* Field request error. */
     867           0 :          jer[0 + *ndjer] = 2;
     868           0 :          *kjer = 1;
     869           0 :          return;
     870             :       }
     871           3 :       subgNum++;
     872             :    }
     873             : 
     874             :    /* Expand the desired subgrid. */
     875         460 :    unpack = ain != NULL || iain != NULL;
     876         460 :    expand = 1;
     877             :    /* The size of c_ipack is *nd5 * sizeof(sInt4) */
     878         460 :    ierr = g2_getfld(c_ipack, *nd5 * sizeof(sInt4), subgNum + 1, unpack, expand, &gfld);
     879         460 :    if (ierr != 0) {
     880           0 :       switch (ierr) {
     881           0 :          case 1:       /* Beginning characters "GRIB" not found. */
     882             :          case 2:       /* GRIB message is not Edition 2. */
     883             :          case 3:       /* The data field request number was not positive. */
     884             :          case 4:       /* End string "7777" found, but not where expected. */
     885             :          case 6:       /* message did not contain requested # of fields */
     886             :          case 7:       /* End string "7777" not found at end of message. */
     887             :          case 8:       /* Unrecognized Section encountered. */
     888           0 :             jer[0 + *ndjer] = 2;
     889           0 :             *kjer = 1;
     890           0 :             break;
     891           0 :          case 15:      /* Error unpacking Section 1. */
     892           0 :             jer[1 + *ndjer] = 2;
     893           0 :             *kjer = 2;
     894           0 :             break;
     895           0 :          case 16:      /* Error unpacking Section 2. */
     896           0 :             jer[2 + *ndjer] = 2;
     897           0 :             *kjer = 3;
     898           0 :             break;
     899           0 :          case 10:      /* Error unpacking Section 3. */
     900           0 :             jer[3 + *ndjer] = 2;
     901           0 :             *kjer = 4;
     902           0 :             break;
     903           0 :          case 11:      /* Error unpacking Section 4. */
     904           0 :             jer[4 + *ndjer] = 2;
     905           0 :             *kjer = 5;
     906           0 :             break;
     907           0 :          case 9:       /* Data Template 5.NN not implemented. */
     908             :          case 12:      /* Error unpacking Section 5. */
     909           0 :             jer[5 + *ndjer] = 2;
     910           0 :             *kjer = 6;
     911           0 :             break;
     912           0 :          case 13:      /* Error unpacking Section 6. */
     913           0 :             jer[6 + *ndjer] = 2;
     914           0 :             *kjer = 7;
     915           0 :             break;
     916           0 :          case 14:      /* Error unpacking Section 7. */
     917           0 :             jer[7 + *ndjer] = 2;
     918           0 :             *kjer = 8;
     919           0 :             break;
     920           0 :          default:
     921           0 :             jer[8 + *ndjer] = 2;
     922           0 :             jer[8] = 9999; /* Unknown error message. */
     923           0 :             *kjer = 9;
     924           0 :             break;
     925             :       }
     926           0 :       g2_free(gfld);
     927           0 :       return;
     928             :    }
     929             :    /* Check if data was not unpacked. */
     930         460 :    if (unpack && !gfld->unpacked) {
     931           0 :       jer[0 + *ndjer] = 2;
     932           0 :       *kjer = 1;
     933           0 :       g2_free(gfld);
     934           0 :       return;
     935             :    }
     936             : 
     937             :    /* Start going through the gfld structure and converting it to the needed
     938             :     * data output formats. */
     939         460 :    myAssert(*ns0 >= 16);
     940         460 :    MEMCPY_BIG(&(is0[0]), c_ipack, sizeof(sInt4));
     941         460 :    is0[6] = gfld->discipline;
     942         460 :    is0[7] = gfld->version;
     943         460 :    MEMCPY_BIG(&(is0[8]), c_ipack + 8, sizeof(sInt4));
     944             :    /* The following assert fails only if the GRIB message is more that 4
     945             :     * giga-bytes large, which I think would break the fortran library. */
     946         460 :    myAssert(is0[8] == 0);
     947         460 :    MEMCPY_BIG(&(is0[8]), c_ipack + 12, sizeof(sInt4));
     948             : 
     949         460 :    myAssert(*ns1 >= 21);
     950         460 :    myAssert(gfld->idsectlen >= 13);
     951         460 :    MEMCPY_BIG(&(is1[0]), c_ipack + 16, sizeof(sInt4));
     952         460 :    is1[4] = c_ipack[20];
     953         460 :    is1[5] = gfld->idsect[0];
     954         460 :    is1[7] = gfld->idsect[1];
     955         460 :    is1[9] = gfld->idsect[2];
     956         460 :    is1[10] = gfld->idsect[3];
     957         460 :    is1[11] = gfld->idsect[4];
     958         460 :    is1[12] = gfld->idsect[5]; /* Year */
     959         460 :    is1[14] = gfld->idsect[6]; /* Month */
     960         460 :    is1[15] = gfld->idsect[7]; /* Day */
     961         460 :    is1[16] = gfld->idsect[8]; /* Hour */
     962         460 :    is1[17] = gfld->idsect[9]; /* Min */
     963         460 :    is1[18] = gfld->idsect[10]; /* Sec */
     964         460 :    is1[19] = gfld->idsect[11];
     965         460 :    is1[20] = gfld->idsect[12];
     966             : 
     967             :    /* Fill out section lengths (separate procedure because of possibility of
     968             :     * having multiple grids.  Should combine fillOutSectLen g2_info, and
     969             :     * g2_getfld into one procedure to optimize it. */
     970         460 :    fillOutSectLen(c_ipack + 16 + is1[0], 4 * *nd5 - 15 - is1[0], subgNum,
     971             :                   is2, is3, is4, is5, is6, is7);
     972             : 
     973             :    /* Check if there is section 2 data. */
     974         460 :    if (gfld->locallen > 0) {
     975             :       /* The + 1 is so we don't overwrite the section length */
     976           2 :       memset((void *)(is2 + 1), 0, (*ns2 - 1) * sizeof(sInt4));
     977           2 :       is2[4] = 2;
     978           2 :       is2[5] = gfld->local[0];
     979             :       /* check if MDL Local use simple packed data */
     980           2 :       if (is2[5] == 1) {
     981           0 :          mdl_LocalUnpack(gfld->local, gfld->locallen, idat, nidat, rdat,
     982             :                          nrdat);
     983             :       } else {
     984             :          /* local use section was not MDL packed, return it in is2. */
     985          26 :          for (i = 0; i < gfld->locallen; i++) {
     986          24 :             is2[i + 5] = gfld->local[i];
     987             :          }
     988             :       }
     989             :    } else {
     990             :       /* API specified that is2[0] = 0; idat[0] = 0, and rdat[0] = 0 */
     991         458 :       is2[0] = 0;
     992         458 :       idat[0] = 0;
     993         458 :       rdat[0] = 0;
     994             :    }
     995             : 
     996         460 :    is3[4] = 3;
     997         460 :    is3[5] = gfld->griddef;
     998         460 :    is3[6] = gfld->ngrdpts;
     999         460 :    if (*nd2x3 < gfld->ngrdpts) {
    1000           0 :       jer[8 + *ndjer] = 2;
    1001           0 :       jer[8] = 2001;    /* nd2x3 is not large enough */
    1002           0 :       *kjer = 9;
    1003           0 :       g2_free(gfld);
    1004           0 :       return;
    1005             :    }
    1006         460 :    is3[10] = gfld->numoct_opt;
    1007         460 :    is3[11] = gfld->interp_opt;
    1008         460 :    is3[12] = gfld->igdtnum;
    1009         460 :    gridIndex = getgridindex(gfld->igdtnum);
    1010         460 :    if (gridIndex == -1) {
    1011           0 :       jer[8 + *ndjer] = 2;
    1012           0 :       jer[8] = 2003;    /* undefined sect 3 template */
    1013           0 :       *kjer = 9;
    1014           0 :       g2_free(gfld);
    1015           0 :       return;
    1016             :    }
    1017         460 :    if( gfld->igdtlen > templatesgrid[gridIndex].mapgridlen )
    1018             :    {
    1019           0 :       jer[8 + *ndjer] = 2;
    1020           0 :       jer[8] = 2003;    /* undefined sect 3 template: FIXME: wrong code probably */
    1021           0 :       *kjer = 9;
    1022           0 :       g2_free (gfld);
    1023           0 :       return;
    1024             :    }
    1025         460 :    curIndex = 14;
    1026        9817 :    for (i = 0; i < gfld->igdtlen; i++) {
    1027        9357 :       if( curIndex < 0 || curIndex >= *ns3 )
    1028             :       {
    1029           0 :         jer[8 + *ndjer] = 2;
    1030           0 :         jer[8] = 2003;    /* undefined sect 3 template: FIXME: wrong code probably */
    1031           0 :         *kjer = 9;
    1032           0 :         g2_free (gfld);
    1033           0 :         return;
    1034             :       }
    1035        9357 :       is3[curIndex] = gfld->igdtmpl[i];
    1036        9357 :       curIndex += abs(templatesgrid[gridIndex].mapgrid[i]);
    1037             :    }
    1038             :    /* API attempts to return grid in scan mode 0100????.  Find the necessary
    1039             :     * indexes into the is3 array for the attempt. */
    1040         460 :    switch (gfld->igdtnum) {
    1041         186 :       case 0:
    1042             :       case 1:
    1043             :       case 2:
    1044             :       case 3:
    1045             :       case 40:
    1046             :       case 41:
    1047             :       case 42:
    1048             :       case 43:
    1049         186 :          scanIndex = 72 - 1;
    1050         186 :          nxIndex = 31 - 1;
    1051         186 :          nyIndex = 35 - 1;
    1052         186 :          break;
    1053         241 :       case 10:
    1054             :       case 12: // Transverse Mercator
    1055         241 :          scanIndex = 60 - 1;
    1056         241 :          nxIndex = 31 - 1;
    1057         241 :          nyIndex = 35 - 1;
    1058         241 :          break;
    1059          26 :       case 20:
    1060             :       case 30:
    1061             :       case 31:
    1062          26 :          scanIndex = 65 - 1;
    1063          26 :          nxIndex = 31 - 1;
    1064          26 :          nyIndex = 35 - 1;
    1065          26 :          break;
    1066           0 :       case 90:
    1067           0 :          scanIndex = 64 - 1;
    1068           0 :          nxIndex = 31 - 1;
    1069           0 :          nyIndex = 35 - 1;
    1070           0 :          break;
    1071           0 :       case 110:
    1072           0 :          scanIndex = 57 - 1;
    1073           0 :          nxIndex = 31 - 1;
    1074           0 :          nyIndex = 35 - 1;
    1075           0 :          break;
    1076           7 :       case 50:
    1077             :       case 51:
    1078             :       case 52:
    1079             :       case 53:
    1080             :       case 100:
    1081             :       case 120:
    1082             :       case 1000:
    1083             :       case 1200:
    1084             :       default:
    1085           7 :          scanIndex = -1;
    1086           7 :          nxIndex = -1;
    1087           7 :          nyIndex = -1;
    1088             :    }
    1089             : 
    1090         460 :    is4[4] = 4;
    1091         460 :    is4[5] = gfld->num_coord;
    1092         460 :    is4[7] = gfld->ipdtnum;
    1093         460 :    pdsIndex = getpdsindex(gfld->ipdtnum);
    1094             : #if 0
    1095             :    if (pdsIndex == -1) {
    1096             :       jer[8 + *ndjer] = 2;
    1097             :       jer[8] = 2004;    /* undefined sect 4 template */
    1098             :       *kjer = 9;
    1099             :       g2_free(gfld);
    1100             :       return;
    1101             :    }
    1102             : #endif
    1103         460 :    if( pdsIndex >= 0 )
    1104             :    {
    1105         457 :    curIndex = 9;
    1106        8056 :    for (i = 0; i < gfld->ipdtlen; i++) {
    1107        7599 :       const struct pdstemplate *templatespds = get_templatespds();
    1108        7599 :       if( curIndex >= *ns4 )
    1109             :       {
    1110             :           /* Should we error out instead ? */
    1111           0 :           break;
    1112             :       }
    1113        7599 :       is4[curIndex] = gfld->ipdtmpl[i];
    1114        7599 :       if( i == MAXPDSMAPLEN )
    1115             :       {
    1116           0 :         jer[8 + *ndjer] = 2;
    1117           0 :         jer[8] = 2004;    /* undefined sect 4 template */
    1118           0 :         *kjer = 9;
    1119           0 :         g2_free (gfld);
    1120           0 :         return;
    1121             :       }
    1122             :       /* 2020-08-04 Taylor: In 2015-10-07, Vuong added the ability for the PDS
    1123             :        * template to have negative forecast times, so data encoded with the
    1124             :        * update has -1 * abs(value).  Unfortunately negative values encoded via
    1125             :        * older versions used 2s complement.  So the updated decoder has to deal
    1126             :        * with both correctly and incorrectly decoded neg values.
    1127             :        *
    1128             :        * To resolve this, negative numbers that are < -1 * 2^30-1 are assumed
    1129             :        * to have been a 2s complement number that was incorrectly decoded.
    1130             :        * */
    1131        7599 :       if (curIndex == 18) {   /* forecast time is stored in octet 18-22 */
    1132         454 :          if (gfld->ipdtmpl[i] < -1 * (0x3fffffff)) {
    1133             :             /* Undoing the incorrect decoding of the negative number. */
    1134           0 :             is4[curIndex] = -1 * (int)(((unsigned)is4[curIndex])^(0x80000000));
    1135             :          }
    1136             :       }
    1137        7599 :       curIndex += abs(templatespds[pdsIndex].mappds[i]);
    1138             :    }
    1139             :    }
    1140             : 
    1141         460 :    is5[4] = 5;
    1142         460 :    is5[5] = gfld->ndpts;
    1143         460 :    is5[9] = gfld->idrtnum;
    1144         460 :    drsIndex = getdrsindex(gfld->idrtnum);
    1145         460 :    if (drsIndex == -1) {
    1146           0 :       jer[8 + *ndjer] = 2;
    1147           0 :       jer[8] = 2005;    /* undefined sect 5 template */
    1148           0 :       *kjer = 9;
    1149           0 :       g2_free(gfld);
    1150           0 :       return;
    1151             :    }
    1152         460 :    curIndex = 11;
    1153        3397 :    for (i = 0; i < gfld->idrtlen; i++) {
    1154        2937 :       const struct drstemplate *templatesdrs = get_templatesdrs();
    1155        2937 :       is5[curIndex] = gfld->idrtmpl[i];
    1156        2937 :       curIndex += abs(templatesdrs[drsIndex].mapdrs[i]);
    1157             :    }
    1158             :    /* Mimic MDL's handling of reference value (IS5(12)) */
    1159         460 :    memcpy(&f_temp, &(is5[11]), sizeof (float));
    1160         460 :    is5[11] = FloatToSInt4Clamp(f_temp);
    1161         460 :    if ((is5[9] == 2) || (is5[9] == 3)) {
    1162          87 :       if (is5[20] == 0) {
    1163          51 :          memcpy(&(f_temp), &(is5[23]), sizeof (float));
    1164          51 :          *xmissp = f_temp;
    1165          51 :          is5[23] = FloatToSInt4Clamp(f_temp);
    1166          51 :          memcpy(&(f_temp), &(is5[27]), sizeof (float));
    1167          51 :          *xmisss = f_temp;
    1168          51 :          is5[27] = FloatToSInt4Clamp(f_temp);
    1169             :       } else {
    1170          36 :          *xmissp = is5[23];
    1171          36 :          *xmisss = is5[27];
    1172             :       }
    1173             :    }
    1174             : 
    1175         460 :    is6[4] = 6;
    1176         460 :    is6[5] = gfld->ibmap;
    1177         460 :    is7[4] = 7;
    1178             : 
    1179         460 :    if (subgNum + 1 == (unsigned int)numfields) {
    1180         451 :       *iendpk = 1;
    1181             :    } else {
    1182           9 :       *iendpk = 0;
    1183             :    }
    1184             : 
    1185         460 :    if ((gfld->ibmap == 0) || (gfld->ibmap == 254)) {
    1186           9 :       *ibitmap = 1;
    1187             :    } else {
    1188         451 :       *ibitmap = 0;
    1189             :    }
    1190             : 
    1191             :    /* Check type of original field, before transferring the memory. */
    1192         460 :    myAssert(*ns5 > 20);
    1193             : 
    1194         460 :    if( ain == NULL && iain == NULL )
    1195             :    {
    1196             :       /* Simulate effect of TransferInt / TransferFloat on the scan flag */
    1197         303 :       if( scanIndex >= 0 && (is3[scanIndex] & 0xf0) != GRIB2BIT_2 )
    1198             :       {
    1199          16 :           is3[scanIndex] = GRIB2BIT_2 + (is3[scanIndex] & 0x0f);
    1200             :       }
    1201             : 
    1202         303 :       g2_free(gfld);
    1203         303 :       return;
    1204             :    }
    1205             : 
    1206             :    /* Check if NCEP had problems expanding the data.  If so we currently
    1207             :     * abort. May need to revisit this behavior. */
    1208         157 :    if (!gfld->expanded) {
    1209           0 :       jer[0 + *ndjer] = 2;
    1210           0 :       *kjer = 1;
    1211           0 :       g2_free(gfld);
    1212           0 :       return;
    1213             :    }
    1214         157 :    f_ignoreScan = 0;
    1215             :    /* Check if integer type... is5[20] == 1 implies integer (code table 5.1),
    1216             :     * but only for certain templates. (0,1,2,3,40,41,40000,40010). (not 4,50,51)
    1217             :     */
    1218         157 :    if ((is5[20] == 1) && ((is5[9] != 4) && (is5[9] != 50) && (is5[9] != 51))) {
    1219             :       /* integer data, use iain */
    1220          67 :       if ((scanIndex < 0) || (nxIndex < 0) || (nyIndex < 0)) {
    1221           1 :          ierr = TransferInt(gfld->fld, gfld->ngrdpts, *ibitmap, gfld->bmap,
    1222             :                             1, &(dummyScan), 0, 0, *iclean, *xmissp,
    1223             :                             iain, *nd2x3, ib);
    1224             :       } else {
    1225          66 :          ierr = TransferInt(gfld->fld, gfld->ngrdpts, *ibitmap, gfld->bmap,
    1226          66 :                             f_ignoreScan, &(is3[scanIndex]), is3[nxIndex],
    1227          66 :                             is3[nyIndex], *iclean, *xmissp, iain, *nd2x3, ib);
    1228             :       }
    1229             :    } else {
    1230             :       /* float data, use ain */
    1231          90 :       if ((scanIndex < 0) || (nxIndex < 0) || (nyIndex < 0)) {
    1232           0 :          ierr = TransferFloat(gfld->fld, gfld->ngrdpts, *ibitmap,
    1233           0 :                               gfld->bmap, 1, &(dummyScan), 0, 0, *iclean,
    1234             :                               *xmissp, ain, *nd2x3, ib);
    1235             :       } else {
    1236          90 :          ierr = TransferFloat(gfld->fld, gfld->ngrdpts, *ibitmap,
    1237          90 :                               gfld->bmap, f_ignoreScan, &(is3[scanIndex]),
    1238          90 :                               is3[nxIndex], is3[nyIndex], *iclean, *xmissp,
    1239             :                               ain, *nd2x3, ib);
    1240             :       }
    1241             :    }
    1242         157 :    if (ierr != 0) {
    1243           0 :       switch (ierr) {
    1244           0 :          case 1:       /* nd2x3 is too small */
    1245           0 :             jer[0 + *ndjer] = 2;
    1246           0 :             *kjer = 1;
    1247           0 :             break;
    1248           0 :          case 2:       /* nx * ny != ngrdpts */
    1249           0 :             jer[5 + *ndjer] = 2;
    1250           0 :             *kjer = 6;
    1251           0 :             break;
    1252           0 :          default:
    1253           0 :             jer[8 + *ndjer] = 2;
    1254           0 :             jer[8] = 9999; /* Unknown error message. */
    1255           0 :             *kjer = 9;
    1256             :       }
    1257           0 :       g2_free(gfld);
    1258           0 :       return;
    1259             :    }
    1260         157 :    g2_free(gfld);
    1261             : }
    1262             : 
    1263             : /*****************************************************************************
    1264             :  * BigByteCpy() --
    1265             :  *
    1266             :  * Arthur Taylor / MDL
    1267             :  *
    1268             :  * PURPOSE
    1269             :  *   This is so we can copy up to 4 bytes from a big endian 4 byte int data
    1270             :  * stream.
    1271             :  *
    1272             :  *   The reason this is needed is because the GRIB2 API required the GRIB2
    1273             :  * message to be passed in as a big endian 4 byte int data stream instead of
    1274             :  * something more reasonable (such as a stream of 1 byte char's)  By having
    1275             :  * this routine we reduce the number of memswaps of the message on a little
    1276             :  * endian system.
    1277             :  *
    1278             :  * ARGUMENTS
    1279             :  *       dst = Where to copy the data to. (Output)
    1280             :  *     ipack = The 4 byte int data stream. (Input)
    1281             :  *       nd5 = length of ipack (Input)
    1282             :  *  startInt = Which integer to start reading in ipack. (Input)
    1283             :  * startByte = Which byte in the startInt to start reading from. (Input)
    1284             :  *   numByte = How many bytes to read. (Input)
    1285             :  *
    1286             :  * FILES/DATABASES: None
    1287             :  *
    1288             :  * RETURNS: NULL
    1289             :  *
    1290             :  * HISTORY
    1291             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1292             :  *
    1293             :  * NOTES
    1294             :  *****************************************************************************
    1295             :  */
    1296             : #if 0
    1297             : static void BigByteCpy(sInt4 *dst, sInt4 *ipack, sInt4 nd5,
    1298             :                        unsigned int startInt, unsigned int startByte,
    1299             :                        int numByte)
    1300             : {
    1301             :    static char Lshift[] = { 0, 8, 16, 24 }; /* Amounts to shift left by. */
    1302             :    unsigned int intIndex; /* Where in ipack to read from. */
    1303             :    unsigned int byteIndex; /* Where in intIndex to read from. */
    1304             :    uInt4 curInt;        /* An unsigned version of the current int. */
    1305             :    unsigned int curByte; /* The current byte we have read. */
    1306             :    int i;               /* Loop counter over number of bytes to read. */
    1307             : 
    1308             :    myAssert(numByte <= 4);
    1309             :    myAssert(startByte < 4);
    1310             :    *dst = 0;
    1311             :    intIndex = startInt;
    1312             :    byteIndex = startByte;
    1313             :    for (i = 0; i < numByte; i++) {
    1314             :        if( intIndex >= (unsigned)nd5 )
    1315             :        {
    1316             :            /* TODO should error out */
    1317             :            return;
    1318             :        }
    1319             :       curInt = (uInt4)ipack[intIndex];
    1320             :       curByte = (curInt << Lshift[byteIndex]) >> 24;
    1321             :       *dst = (sInt4)((unsigned)*dst << 8) + curByte;
    1322             :       byteIndex++;
    1323             :       if (byteIndex == 4) {
    1324             :          byteIndex = 0;
    1325             :          intIndex++;
    1326             :       }
    1327             :    }
    1328             : }
    1329             : #endif
    1330             : 
    1331             : /*****************************************************************************
    1332             :  * FindTemplateIDs() --
    1333             :  *
    1334             :  * Arthur Taylor / MDL
    1335             :  *
    1336             :  * PURPOSE
    1337             :  *   This is so we can find out which templates are in this GRIB2 message.
    1338             :  * Which allows us to determine if we can call the MDL routines, or if we
    1339             :  * should call the NCEP routines instead.
    1340             :  *
    1341             :  * ARGUMENTS
    1342             :  *      ipack = The 4 byte int data stream. (Input)
    1343             :  *        nd5 = length of ipack (Input)
    1344             :  *    subgNum = Which subgrid to look at. (Input)
    1345             :  *    gdsTmpl = The gds template number for this subgrid. (Output)
    1346             :  *    pdsTmpl = The pds template number for this subgrid. (Output)
    1347             :  *    drsTmpl = The drs template number for this subgrid. (Output)
    1348             :  * f_noBitmap = 0 has a bitmap, else doesn't have a bitmap. (Output)
    1349             :  *  orderDiff = The order of the differencing in template 5.3 (1st, 2nd) (out)
    1350             :  *
    1351             :  * FILES/DATABASES: None
    1352             :  *
    1353             :  * RETURNS: int
    1354             :  *  0 = Ok.
    1355             :  *  2 = invalid section number
    1356             :  *
    1357             :  * HISTORY
    1358             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1359             :  *
    1360             :  * NOTES
    1361             :  *****************************************************************************
    1362             :  */
    1363             : #if 0
    1364             : static int FindTemplateIDs(sInt4 *ipack, sInt4 nd5, int subgNum,
    1365             :                            sInt4 *gdsTmpl, sInt4 *pdsTmpl,
    1366             :                            sInt4 *drsTmpl, sInt4 *numGrps,
    1367             :                            uChar *f_noBitmap, sInt4 *orderDiff)
    1368             : {
    1369             :    unsigned int gNum = 0; /* Which sub group we are currently working with. */
    1370             :    sInt4 offset;        /* Where in the bytes stream we currently are. */
    1371             :    sInt4 sectLen;       /* The length of the current section. */
    1372             :    sInt4 sectId;        /* The current section number. */
    1373             :    sInt4 li_temp;       /* A temporary holder for the bitmap flag. */
    1374             : 
    1375             :    /* Jump over section 0. */
    1376             :    offset = 16;
    1377             :    while (gNum <= (unsigned int)subgNum) {
    1378             :       BigByteCpy(&sectLen, ipack, nd5, (offset / 4), (offset % 4), 4);
    1379             :       /* Check if we just read section 8.  If so, then it is "7777" =
    1380             :        * 926365495 regardless of endian'ness. */
    1381             :       if (sectLen == 926365495L) {
    1382             : #ifdef DEBUG
    1383             :          printf("Shouldn't see sect 8. Should stop after correct sect 5\n");
    1384             : #endif
    1385             :          return 2;
    1386             :       }
    1387             :       BigByteCpy(&sectId, ipack, nd5, ((offset + 4) / 4),
    1388             :                  ((offset + 4) % 4), 1);
    1389             :       switch (sectId) {
    1390             :          case 1:
    1391             :          case 2:
    1392             :             break;
    1393             :          case 3:
    1394             :             BigByteCpy(gdsTmpl, ipack, nd5, ((offset + 12) / 4),
    1395             :                        ((offset + 12) % 4), 2);
    1396             :             break;
    1397             :          case 4:
    1398             :             BigByteCpy(pdsTmpl, ipack, nd5, ((offset + 7) / 4),
    1399             :                        ((offset + 7) % 4), 2);
    1400             :             break;
    1401             :          case 5:
    1402             :             BigByteCpy(drsTmpl, ipack, nd5, ((offset + 9) / 4),
    1403             :                        ((offset + 9) % 4), 2);
    1404             :             if ((*drsTmpl == 2) || (*drsTmpl == 3)) {
    1405             :                BigByteCpy(numGrps, ipack, nd5, ((offset + 31) / 4),
    1406             :                           ((offset + 31) % 4), 4);
    1407             :             } else {
    1408             :                *numGrps = 0;
    1409             :             }
    1410             :             if (*drsTmpl == 3) {
    1411             :                BigByteCpy(&li_temp, ipack, nd5, ((offset + 44) / 4),
    1412             :                           ((offset + 44) % 4), 1);
    1413             :                *orderDiff = li_temp;
    1414             :             } else {
    1415             :                *orderDiff = 0;
    1416             :             }
    1417             :             break;
    1418             :          case 6:
    1419             :             BigByteCpy(&li_temp, ipack, nd5, ((offset + 5) / 4),
    1420             :                        ((offset + 5) % 4), 1);
    1421             :             if (li_temp == 255) {
    1422             :                *f_noBitmap = 1;
    1423             :             }
    1424             :             gNum++;
    1425             :             break;
    1426             :          case 7:
    1427             :             break;
    1428             :          default:
    1429             : #ifdef DEBUG
    1430             :             printf("Invalid section id %d.\n", sectId);
    1431             : #endif
    1432             :             return 2;
    1433             :       }
    1434             :       offset += sectLen;
    1435             :    }
    1436             :    return 0;
    1437             : }
    1438             : #endif
    1439             : 
    1440             : /*****************************************************************************
    1441             :  * unpk_grib2() --
    1442             :  *
    1443             :  * Arthur Taylor / MDL
    1444             :  *
    1445             :  * PURPOSE
    1446             :  *   This procedure is the main API for decoding GRIB2 messages.  It is
    1447             :  * intended to be a branching routine to call either the MDL GRIB2 library,
    1448             :  * or the NCEP GRIB2 library, depending on which template it sees in the
    1449             :  * message.
    1450             :  *
    1451             :  * ARGUMENTS
    1452             :  *  kfildo = Unit number for output diagnostics (C ignores this). (Input)
    1453             :  *     ain = contains the data if the original data was float data.
    1454             :  *           (size = nd2x3) (Output)
    1455             :  *    iain = contains the data if the original data was integer data.
    1456             :  *           (size = nd2x3) (Output)
    1457             :  *   nd2x3 = length of ain, iain, ib (Input)
    1458             :  *           (at least the size of num grid points)
    1459             :  *    idat = local use data if any that were unpacked from Section 2. (Output)
    1460             :  *   nidat = length of idat. (Input)
    1461             :  *    rdat = floating point local use data (Output)
    1462             :  *   nrdat = length of rdat. (Input)
    1463             :  *     is0 = Section 0 data (Output)
    1464             :  *     ns0 = length of is0 (16 is fine) (Input)
    1465             :  *     is1 = Section 1 data (Output)
    1466             :  *     ns1 = length of is1 (21 is fine) (Input)
    1467             :  *     is2 = Section 2 data (Output)
    1468             :  *     ns2 = length of is2 () (Input)
    1469             :  *     is3 = Section 3 data (Output)
    1470             :  *     ns3 = length of is3 (96 or 1600) (Input)
    1471             :  *     is4 = Section 4 data (Output)
    1472             :  *     ns4 = length of is4 (60) (Input)
    1473             :  *     is5 = Section 5 data (Output)
    1474             :  *     ns5 = length of is5 (49 is fine) (Input)
    1475             :  *     is6 = Section 6 data (Output)
    1476             :  *     ns6 = length of is6 (6 is fine) (Input)
    1477             :  *     is7 = Section 7 data (Output)
    1478             :  *     ns7 = length of is7 (8 is fine) (Input)
    1479             :  *      ib = Bitmap if user requested it, and it was packed (Output)
    1480             :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Output)
    1481             :  *   ipack = The message to unpack (This is assumed to be Big endian) (Input)
    1482             :  *     nd5 = The size of ipack (Input)
    1483             :  *  xmissp = The floating point representation for the primary missing value.
    1484             :  *           (Input/Output)
    1485             :  *  xmisss = The floating point representation for the secondary missing
    1486             :  *           value (Input/Output)
    1487             :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
    1488             :  *  iclean = 1 means the user wants the unpacked data returned without
    1489             :  *           missing values in it. 0 means embed the missing values. (Input)
    1490             :  *  l3264b = Integer word length in bits (32 or 64) (Input)
    1491             :  *  iendpk = A 1 means no more grids in this message, a 0 means more grids.
    1492             :  *           (Output)
    1493             :  * jer(ndjer,2) = error codes along with severity. (Output)
    1494             :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
    1495             :  *    kjer = number of error messages stored in jer. (Output)
    1496             :  *
    1497             :  * FILES/DATABASES: None
    1498             :  *
    1499             :  * RETURNS: void
    1500             :  *
    1501             :  * HISTORY
    1502             :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1503             :  *
    1504             :  * NOTES
    1505             :  * Inefficiencies: have to memswap ipack multiple times.
    1506             :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
    1507             :  * MDL attempts to always return grids in scan mode 0100????
    1508             :  * ToDo: Check length of parameters better.
    1509             :  *
    1510             :  * According to MDL's unpk_grib2.f, it currently supports (so for others we
    1511             :  * call the NCEP routines):
    1512             :  *    TEMPLATE 3.0   EQUIDISTANT CYLINDRICAL LATITUDE/LONGITUDE
    1513             :  *    TEMPLATE 3.10  MERCATOR
    1514             :  *    TEMPLATE 3.20  POLAR STEREOGRAPHIC
    1515             :  *    TEMPLATE 3.30  LAMBERT
    1516             :  *    TEMPLATE 3.90  ORTHOGRAPHIC SPACE VIEW
    1517             :  *    TEMPLATE 3.110 EQUATORIAL AZIMUTHAL EQUIDISTANT
    1518             :  *    TEMPLATE 3.120 AZIMUTH-RANGE (RADAR)
    1519             :  *
    1520             :  *    TEMPLATE 4.0  ANALYSIS OR FORECAST AT A LEVEL AND POINT
    1521             :  *    TEMPLATE 4.1  INDIVIDUAL ENSEMBLE
    1522             :  *    TEMPLATE 4.2  DERIVED FORECAST BASED ON ENSEMBLES
    1523             :  *    TEMPLATE 4.8  AVERAGE, ACCUMULATION, EXTREMES
    1524             :  *    TEMPLATE 4.20 RADAR
    1525             :  *    TEMPLATE 4.30 SATELLITE
    1526             :  *
    1527             :  *    TEMPLATE 5.0  SIMPLE PACKING
    1528             :  *    TEMPLATE 5.2  COMPLEX PACKING
    1529             :  *    TEMPLATE 5.3  COMPLEX PACKING AND SPATIAL DIFFERENCING
    1530             :  *
    1531             :  * Correction to "unpk_grib2.f" : It also supports:
    1532             :  *    TEMPLATE 4.9  Probability forecast in a time interval
    1533             :  *
    1534             :  *****************************************************************************
    1535             :  */
    1536             : #ifdef unused_by_GDAL
    1537             : void unpk_grib2(sInt4 *kfildo, float *ain, sInt4 *iain, sInt4 *nd2x3,
    1538             :                 sInt4 *idat, sInt4 *nidat, float *rdat, sInt4 *nrdat,
    1539             :                 sInt4 *is0, sInt4 *ns0, sInt4 *is1, sInt4 *ns1,
    1540             :                 sInt4 *is2, sInt4 *ns2, sInt4 *is3, sInt4 *ns3,
    1541             :                 sInt4 *is4, sInt4 *ns4, sInt4 *is5, sInt4 *ns5,
    1542             :                 sInt4 *is6, sInt4 *ns6, sInt4 *is7, sInt4 *ns7,
    1543             :                 sInt4 *ib, sInt4 *ibitmap, sInt4 *ipack, sInt4 *nd5,
    1544             :                 float *xmissp, float *xmisss, sInt4 *inew,
    1545             :                 sInt4 *iclean, sInt4 *l3264b, sInt4 *iendpk, sInt4 *jer,
    1546             :                 sInt4 *ndjer, sInt4 *kjer)
    1547             : {
    1548             :    unsigned char *c_ipack; /* The compressed data as char instead of sInt4 so
    1549             :                             * it is easier to work with. */
    1550             : #if 0
    1551             :    char f_useMDL = 0;   /* Instructed 3/8/2005 10:30 to not use MDL. */
    1552             : #endif
    1553             : 
    1554             :    /* Since NCEP's code works with byte level stuff, we need to un-do the
    1555             :     * byte swap of the (int *) data, then cast it to an (unsigned char *) */
    1556             : #ifndef WORDS_BIGENDIAN
    1557             :    /* Can't make this dependent on inew, since they could have a sequence of
    1558             :     * get first message... do stuff, get second message, which unfortunately
    1559             :     * means they would have to get the first message again, causing 2 swaps,
    1560             :     * and breaking their second request for the first message (as well as
    1561             :     * their second message). */
    1562             :    memswp(ipack, sizeof(sInt4), *nd5);
    1563             : #endif
    1564             :    c_ipack = (unsigned char *)ipack;
    1565             :    unpk_g2ncep(kfildo, ain, iain, nd2x3, idat, nidat, rdat, nrdat, is0,
    1566             :                ns0, is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5,
    1567             :                is6, ns6, is7, ns7, ib, ibitmap, c_ipack, nd5, xmissp,
    1568             :                xmisss, inew, iclean, l3264b, iendpk, jer, ndjer, kjer);
    1569             : 
    1570             : #ifndef WORDS_BIGENDIAN
    1571             :    /* Swap back because we could be called again for the subgrid data. */
    1572             :    memswp(ipack, sizeof(sInt4), *nd5);
    1573             : #endif
    1574             : }
    1575             : #endif
    1576             : 
    1577             : /*****************************************************************************
    1578             :  * C_pkGrib2() --
    1579             :  *
    1580             :  * Arthur Taylor / MDL
    1581             :  *
    1582             :  * PURPOSE
    1583             :  *   This procedure is the main API for encoding GRIB2 messages.  It is
    1584             :  * intended to call NCEP's GRIB2 library.
    1585             :  *
    1586             :  * RETURNS: void
    1587             :  *
    1588             :  * HISTORY
    1589             :  *   1/2004 Arthur Taylor (MDL/RSIS): Created.
    1590             :  *
    1591             :  * NOTES
    1592             :  *****************************************************************************
    1593             :  */
    1594             : 
    1595             : #ifdef unused_by_GDAL
    1596             : int C_pkGrib2(unsigned char *cgrib, sInt4 *sec0, sInt4 *sec1,
    1597             :               unsigned char *csec2, sInt4 lcsec2,
    1598             :               sInt4 *igds, sInt4 *igdstmpl, sInt4 *ideflist,
    1599             :               sInt4 idefnum, sInt4 ipdsnum, sInt4 *ipdstmpl,
    1600             :               float *coordlist, sInt4 numcoord, sInt4 idrsnum,
    1601             :               sInt4 *idrstmpl, float *fld, sInt4 ngrdpts,
    1602             :               sInt4 ibmap, sInt4 *bmap)
    1603             : {
    1604             :    int ierr;            /* error value from grib2 library. */
    1605             : 
    1606             :    if ((ierr = g2_create(cgrib, sec0, sec1)) == -1) {
    1607             :       /* Tried to use for version other than GRIB Ed 2 */
    1608             :       return -1;
    1609             :    }
    1610             : 
    1611             :    if ((ierr = g2_addlocal(cgrib, csec2, lcsec2)) < 0) {
    1612             :       /* Some how got a bad section 2.  Should be impossible unless an assert
    1613             :        * was broken. */
    1614             :       return -2;
    1615             :    }
    1616             : 
    1617             :    if ((ierr = g2_addgrid(cgrib, igds, igdstmpl, ideflist, idefnum)) < 0) {
    1618             :       /* Some how got a bad section 3.  Only way would be should be with an
    1619             :        * unsupported template number unless an assert was broken. */
    1620             :       return -3;
    1621             :    }
    1622             : 
    1623             :    if ((ierr = g2_addfield(cgrib, ipdsnum, ipdstmpl, coordlist, numcoord,
    1624             :                            idrsnum, idrstmpl, fld, ngrdpts, ibmap,
    1625             :                            bmap)) < 0) {
    1626             :       return -4;
    1627             :    }
    1628             : 
    1629             :    if ((ierr = g2_gribend(cgrib)) < 0) {
    1630             :       return -5;
    1631             :    }
    1632             : 
    1633             :    return ierr;
    1634             : }
    1635             : #endif /* unused_by_GDAL */

Generated by: LCOV version 1.14