LCOV - code coverage report
Current view: directory - frmts/grib/degrib18/degrib - grib2api.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 495 210 42.4 %
Date: 2011-12-18 Functions: 11 6 54.5 %

       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 <stdlib.h>
      17                 : #include <string.h>
      18                 : #include <math.h>
      19                 : #include "grib2api.h"
      20                 : #include "grib2.h"
      21                 : #include "scan.h"
      22                 : #include "memendian.h"
      23                 : #include "myassert.h"
      24                 : #include "gridtemplates.h"
      25                 : #include "pdstemplates.h"
      26                 : #include "drstemplates.h"
      27                 : 
      28                 : //#include "config.h" /*config.h created by configure - ADT mod*/
      29                 : 
      30                 : /* Declare the external FORTRAN routine
      31                 :  * gcc has two __ if there is one _ in the procedure name. */
      32                 : #ifdef _FORTRAN
      33                 :    extern void UNPK_G2MDL
      34                 :    (sInt4 * kfildo, sInt4 * jmin, sInt4 * lbit, sInt4 * nov, sInt4 * iwork,
      35                 :    float * ain, sInt4 * iain, sInt4 * nd2x3, sInt4 * idat, sInt4 * nidat,
      36                 :    float * rdat, sInt4 * nrdat, sInt4 * is0, sInt4 * ns0, sInt4 * is1,
      37                 :    sInt4 * ns1, sInt4 * is2, sInt4 * ns2, sInt4 * is3, sInt4 * ns3,
      38                 :    sInt4 * is4, sInt4 * ns4, sInt4 * is5, sInt4 * ns5, sInt4 * is6,
      39                 :    sInt4 * ns6, sInt4 * is7, sInt4 * ns7, sInt4 * ib, sInt4 * ibitmap,
      40                 :    sInt4 * ipack, sInt4 * nd5, float * xmissp, float * xmisss,
      41                 :    sInt4 * inew, sInt4 * iclean, sInt4 * l3264b, sInt4 * iendpk, sInt4 * jer,
      42                 :    sInt4 * ndjer, sInt4 * kjer);
      43                 : 
      44                 :    extern void PK_G2MDL
      45                 :    (sInt4 * kfildo, sInt4 * jmax, sInt4 * jmin, sInt4 * lbit, sInt4 * nov,
      46                 :    sInt4 * misslx, float * a, sInt4 * ia, sInt4 * newbox, sInt4 * newboxp,
      47                 :    float * ain, sInt4 * iain, sInt4 * nx, sInt4 * ny, sInt4 * idat,
      48                 :    sInt4 * nidat, float * rdat, sInt4 * nrdat, sInt4 * is0, sInt4 * ns0,
      49                 :    sInt4 * is1, sInt4 * ns1, sInt4 * is3, sInt4 * ns3, sInt4 * is4,
      50                 :    sInt4 * ns4, sInt4 * is5, sInt4 * ns5, sInt4 * is6, sInt4 * ns6,
      51                 :    sInt4 * is7, sInt4 * ns7, sInt4 * ib, sInt4 * ibitmap, sInt4 * ipack,
      52                 :    sInt4 * nd5, sInt4 * missp, float * xmissp, sInt4 * misss,
      53                 :    float * xmisss, sInt4 * inew, sInt4 * minpk, sInt4 * iclean,
      54                 :    sInt4 * l3264b, sInt4 * jer, sInt4 * ndjer, sInt4 * kjer);
      55                 : #endif
      56                 : 
      57                 : /*****************************************************************************
      58                 :  * mdl_LocalUnpack() --
      59                 :  *
      60                 :  * Arthur Taylor / MDL
      61                 :  *
      62                 :  * PURPOSE
      63                 :  *   Unpack the local use data assuming that it was packed using the MDL
      64                 :  * encoder.  This assumes "local" starts at octet 6 (ie skipping over the
      65                 :  * length and section ID octets)
      66                 :  *
      67                 :  *   In Section 2, GRIB2 provides for local use data.  The MDL encoder packs
      68                 :  * that data, and signifies that it has done so by setting octet 6 to 1.
      69                 :  * This may have been inadvisable, since the GRIB2 specs did not state that
      70                 :  * octet 6 was special.
      71                 :  *
      72                 :  * ARGUMENTS
      73                 :  *    local = The section 2 data prior to being unpacked. (Input)
      74                 :  * locallen = The length of "local" (Input)
      75                 :  *     idat = Unpacked MDL local data (if it was an integer) (Output)
      76                 :  *    nidat = length of idat. (Input)
      77                 :  *     rdat = Unpacked MDL local data (if it was a float) (Output)
      78                 :  *    nrdat = length of rdat. (Input)
      79                 :  *
      80                 :  * FILES/DATABASES: None
      81                 :  *
      82                 :  * RETURNS: int
      83                 :  *  0 = Ok.
      84                 :  *  1 = Mixed local data types?
      85                 :  *  2 = nrdat is not large enough.
      86                 :  *  3 = nidat is not large enough.
      87                 :  *  4 = Too many bits to unpack, should be a max of 32 bits.
      88                 :  *  5 = Locallen is too small
      89                 :  *
      90                 :  * HISTORY
      91                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
      92                 :  *
      93                 :  * NOTES
      94                 :  *****************************************************************************
      95                 :  */
      96                 : #define GRIB_UNSIGN_INT2(a,b) ((a<<8)+b)
      97               0 : static int mdl_LocalUnpack (unsigned char *local, sInt4 locallen,
      98                 :                             sInt4 * idat, sInt4 * nidat, float * rdat,
      99                 :                             sInt4 * nrdat)
     100                 : {
     101               0 :    int BytesUsed = 0;   /* How many bytes have been used. */
     102                 :    unsigned int numGroup; /* Number of groups */
     103                 :    int i;               /* Counter over the groups. */
     104                 :    sInt4 numVal;        /* Number of values in a given group. */
     105                 :    float refVal;       /* The reference value in a given group. */
     106                 :    unsigned int scale;  /* The power of 10 scale value in the group. */
     107                 :    sInt4 recScale10;    /* 1 / 10**scale.. For faster computations. */
     108                 :    unsigned char numBits; /* # of bits for a single element in the group. */
     109                 :    char f_dataType;     /* If the local data is a float or integer. */
     110               0 :    char f_firstType = 0; /* The type of the first group of local data. */
     111               0 :    int curIndex = 0;    /* Where to store the current data. */
     112                 :    int j;               /* Counter over the number of values in a group. */
     113                 :    size_t numUsed;      /* Number of bytes used in call to memBitRead. */
     114                 :    uChar bufLoc;   /* Where to read for more bits in the data stream. */
     115                 :    uInt4 uli_temp; /* Temporary storage to hold unpacked data. */
     116                 : 
     117               0 :    if (locallen < BytesUsed + 3) {
     118                 : #ifdef DEBUG
     119               0 :       printf ("Locallen is too small.\n");
     120                 : #endif
     121               0 :       return 5;
     122                 :    }
     123                 :    /* The calling routine should check octet 6, which is local[0], to be 1,
     124                 :     * so we just assert it is 1. */
     125               0 :    myAssert (local[0] == 1);
     126               0 :    numGroup = GRIB_UNSIGN_INT2 (local[1], local[2]);
     127               0 :    local += 3;
     128               0 :    BytesUsed += 3;
     129               0 :    myAssert (*nrdat > 1);
     130               0 :    myAssert (*nidat > 1);
     131               0 :    idat[0] = 0;
     132               0 :    rdat[0] = 0;
     133                 : 
     134               0 :    for (i = 0; i < numGroup; i++) {
     135               0 :       if (locallen < BytesUsed + 12) {
     136                 : #ifdef DEBUG
     137               0 :          printf ("Locallen is too small.\n");
     138                 : #endif
     139               0 :          return 5;
     140                 :       }
     141               0 :       MEMCPY_BIG (&numVal, local, sizeof (sInt4));
     142               0 :       MEMCPY_BIG (&refVal, local + 4, sizeof (float));
     143               0 :       scale = GRIB_UNSIGN_INT2 (local[8], local[9]);
     144               0 :       recScale10 = 1 / pow (10.0, scale);
     145               0 :       numBits = local[10];
     146               0 :       if (numBits >= 32) {
     147                 : #ifdef DEBUG
     148               0 :          printf ("Too many bits too unpack.\n");
     149                 : #endif
     150               0 :          return 4;
     151                 :       }
     152               0 :       f_dataType = local[11];
     153               0 :       local += 12;
     154               0 :       BytesUsed += 12;
     155               0 :       if (locallen < BytesUsed + ((numBits * numVal) + 7) / 8) {
     156                 : #ifdef DEBUG
     157               0 :          printf ("Locallen is too small.\n");
     158                 : #endif
     159               0 :          return 5;
     160                 :       }
     161               0 :       if (i == 0) {
     162               0 :          f_firstType = f_dataType;
     163               0 :       } else if (f_firstType != f_dataType) {
     164                 : #ifdef DEBUG
     165               0 :          printf ("Local use data has mixed float/integer type?\n");
     166                 : #endif
     167               0 :          return 1;
     168                 :       }
     169               0 :       bufLoc = 8;
     170               0 :       if (f_dataType == 0) {
     171                 :          /* Floating point data. */
     172               0 :          if (*nrdat < (curIndex + numVal + 3)) {
     173                 : #ifdef DEBUG
     174               0 :             printf ("nrdat is not large enough.\n");
     175                 : #endif
     176               0 :             return 2;
     177                 :          }
     178               0 :          rdat[curIndex] = numVal;
     179               0 :          curIndex++;
     180               0 :          rdat[curIndex] = scale;
     181               0 :          curIndex++;
     182               0 :          for (j = 0; j < numVal; j++) {
     183               0 :             memBitRead (&uli_temp, sizeof (sInt4), local, numBits,
     184                 :                         &bufLoc, &numUsed);
     185               0 :             local += numUsed;
     186               0 :             BytesUsed += numUsed;
     187               0 :             rdat[curIndex] = (refVal + uli_temp) * recScale10;
     188               0 :             curIndex++;
     189                 :          }
     190               0 :          rdat[curIndex] = 0;
     191                 :       } else {
     192                 :          /* Integer point data. */
     193               0 :          if (*nidat < (curIndex + numVal + 3)) {
     194                 : #ifdef DEBUG
     195               0 :             printf ("nidat is not large enough.\n");
     196                 : #endif
     197               0 :             return 3;
     198                 :          }
     199               0 :          idat[curIndex] = numVal;
     200               0 :          curIndex++;
     201               0 :          idat[curIndex] = scale;
     202               0 :          curIndex++;
     203               0 :          for (j = 0; j < numVal; j++) {
     204               0 :             memBitRead (&uli_temp, sizeof (sInt4), local, numBits,
     205                 :                         &bufLoc, &numUsed);
     206               0 :             local += numUsed;
     207               0 :             BytesUsed += numUsed;
     208               0 :             idat[curIndex] = (refVal + uli_temp) * recScale10;
     209               0 :             curIndex++;
     210                 :          }
     211               0 :          idat[curIndex] = 0;
     212                 :       }
     213                 :    }
     214               0 :    return 0;
     215                 : }
     216                 : 
     217                 : /*****************************************************************************
     218                 :  * fillOutSectLen() --
     219                 :  *
     220                 :  * Arthur Taylor / MDL
     221                 :  *
     222                 :  * PURPOSE
     223                 :  *   The GRIB2 API returns the lengths of each GRIB2 section along with the
     224                 :  * meta data.  NCEP's routines did not, so this routine fills in that part.
     225                 :  * This routine has to consider which grid is being unpacked.
     226                 :  *
     227                 :  *   c_ipack is passed in after section 1 (since section 1 is not repeated)
     228                 :  *
     229                 :  * ARGUMENTS
     230                 :  *  c_ipack = Complete GRIB2 message to look for the section lengths in. (In)
     231                 :  * lenCpack = Length of c_ipack (Input)
     232                 :  *  subgNum = Which sub rid to find the section lengths of. (Input)
     233                 :  *      is2 = Section 2 data (Output)
     234                 :  *      is3 = Section 3 data (Output)
     235                 :  *      is4 = Section 4 data (Output)
     236                 :  *      is5 = Section 5 data (Output)
     237                 :  *      is6 = Section 6 data (Output)
     238                 :  *      is7 = Section 7 data (Output)
     239                 :  *
     240                 :  * FILES/DATABASES: None
     241                 :  *
     242                 :  * RETURNS: int
     243                 :  *  0 = Ok.
     244                 :  *  1 = c_ipack is not large enough
     245                 :  *  2 = invalid section number
     246                 :  *
     247                 :  * HISTORY
     248                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     249                 :  *
     250                 :  * NOTES
     251                 :  *****************************************************************************
     252                 :  */
     253               2 : static int fillOutSectLen (unsigned char *c_ipack, int lenCpack,
     254                 :                            int subgNum, sInt4 * is2, sInt4 * is3,
     255                 :                            sInt4 * is4, sInt4 * is5, sInt4 * is6,
     256                 :                            sInt4 * is7)
     257                 : {
     258               2 :    sInt4 offset = 0;    /* How far in c_ipack we have read. */
     259                 :    sInt4 sectLen;       /* The length of the current section. */
     260                 :    int sectId;          /* The current section number. */
     261               2 :    unsigned int gNum = 0; /* Which sub group we are currently working with. */
     262                 : 
     263               2 :    if (lenCpack < 5) {
     264                 : #ifdef DEBUG
     265               0 :       printf ("Cpack is not large enough.\n");
     266                 : #endif
     267               0 :       return 1;
     268                 :    }
     269                 :    /* assert that we start with data in either section 2 or 3. */
     270               2 :    myAssert ((c_ipack[4] == 2) || (c_ipack[4] == 3));
     271              14 :    while (gNum <= subgNum) {
     272              10 :       if (lenCpack < offset + 5) {
     273                 : #ifdef DEBUG
     274               0 :          printf ("Cpack is not large enough.\n");
     275                 : #endif
     276               0 :          return 1;
     277                 :       }
     278              10 :       MEMCPY_BIG (&sectLen, c_ipack + offset, sizeof (sInt4));
     279                 :       /* Check if we just read section 8.  If so, then it is "7777" =
     280                 :        * 926365495 regardless of endian'ness. */
     281              10 :       if (sectLen == 926365495L) {
     282                 : #ifdef DEBUG
     283               0 :          printf ("Shouldn't see sect 8. Should stop after correct sect 7\n");
     284                 : #endif
     285               0 :          return 2;
     286                 :       }
     287              10 :       sectId = c_ipack[offset + 4];
     288              10 :       switch (sectId) {
     289                 :          case 2:
     290               0 :             is2[0] = sectLen;
     291               0 :             break;
     292                 :          case 3:
     293               2 :             is3[0] = sectLen;
     294               2 :             break;
     295                 :          case 4:
     296               2 :             is4[0] = sectLen;
     297               2 :             break;
     298                 :          case 5:
     299               2 :             is5[0] = sectLen;
     300               2 :             break;
     301                 :          case 6:
     302               2 :             is6[0] = sectLen;
     303               2 :             break;
     304                 :          case 7:
     305               2 :             is7[0] = sectLen;
     306               2 :             gNum++;
     307               2 :             break;
     308                 :          default:
     309                 : #ifdef DEBUG
     310               0 :             printf ("Invalid section id %d.\n", sectId);
     311                 : #endif
     312               0 :             return 2;
     313                 :       }
     314              10 :       offset += sectLen;
     315                 :    }
     316               2 :    return 0;
     317                 : }
     318                 : 
     319                 : /*****************************************************************************
     320                 :  * TransferInt() --
     321                 :  *
     322                 :  * Arthur Taylor / MDL
     323                 :  *
     324                 :  * PURPOSE
     325                 :  *   To transfer the data from "fld" and "bmap" to "iain" and "ib".  The API
     326                 :  * attempts to rearrange the order, so that anything returned from it has
     327                 :  * scan mode 0100????
     328                 :  *
     329                 :  * ARGUMENTS
     330                 :  *          fld = The expanded grid from NCEPs routines (Input)
     331                 :  *      ngrdpts = Length of fld (Input)
     332                 :  *      ibitmap = flag if we have a bitmap or not. (Input)
     333                 :  *         bmap = bitmap from NCEPs routines. (Input)
     334                 :  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
     335                 :  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
     336                 :  *       nx, ny = The dimmensions of the grid. (Input)
     337                 :  *       iclean = 1 means the user wants the unpacked data returned without
     338                 :  *                missing values in it. 0 means embed the missing values. (In)
     339                 :  *       xmissp = The primary missing value to use if iclean = 0. (Input).
     340                 :  *         iain = The grid to return. (Output)
     341                 :  *        nd2x3 = The length of iain. (Input)
     342                 :  *           ib = Bitmap if it was packed (Output)
     343                 :  *
     344                 :  * FILES/DATABASES: None
     345                 :  *
     346                 :  * RETURNS: int
     347                 :  *  0 = Ok.
     348                 :  *  1 = nd2x3 is too small.
     349                 :  *  2 = nx*ny != ngrdpts
     350                 :  *
     351                 :  * HISTORY
     352                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     353                 :  *
     354                 :  * NOTES
     355                 :  *   May want to disable the scan adjustment in the future.
     356                 :  *****************************************************************************
     357                 :  */
     358               0 : static int TransferInt (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
     359                 :                         sInt4 * bmap, char f_ignoreScan, sInt4 * scan,
     360                 :                         sInt4 nx, sInt4 ny, sInt4 iclean, float xmissp,
     361                 :                         sInt4 * iain, sInt4 nd2x3, sInt4 * ib)
     362                 : {
     363                 :    int i;               /* loop counter over all grid points. */
     364                 :    sInt4 x, y;       /* Where we are in a grid of scan value 0100???? */
     365                 :    int curIndex;        /* Where in iain to store the current data. */
     366                 : 
     367               0 :    if (nd2x3 < ngrdpts) {
     368                 : #ifdef DEBUG
     369               0 :       printf ("nd2x3(%d) is < ngrdpts(%d)\n", nd2x3, ngrdpts);
     370                 : #endif
     371               0 :       return 1;
     372                 :    }
     373               0 :    if (f_ignoreScan || ((*scan & 0xf0) == 64)) {
     374               0 :       if (ibitmap) {
     375               0 :          for (i = 0; i < ngrdpts; i++) {
     376               0 :             ib[i] = bmap[i];
     377                 :             /* Check if we are supposed to insert xmissp into the field */
     378               0 :             if ((iclean != 0) && (ib[i] == 0)) {
     379               0 :                iain[i] = xmissp;
     380                 :             } else {
     381               0 :                iain[i] = fld[i];
     382                 :             }
     383                 :          }
     384                 :       } else {
     385               0 :          for (i = 0; i < ngrdpts; i++) {
     386               0 :             iain[i] = fld[i];
     387                 :          }
     388                 :       }
     389                 :    } else {
     390               0 :       if (nx * ny != ngrdpts) {
     391                 : #ifdef DEBUG
     392               0 :          printf ("nx * ny (%d) != ngrdpts(%d)\n", nx * ny, ngrdpts);
     393                 : #endif
     394               0 :          return 2;
     395                 :       }
     396               0 :       if (ibitmap) {
     397               0 :          for (i = 0; i < ngrdpts; i++) {
     398               0 :             ScanIndex2XY (i, &x, &y, *scan, nx, ny);
     399                 :             /* ScanIndex returns value as if scan was 0100(0000) */
     400               0 :             curIndex = (x - 1) + (y - 1) * nx;
     401               0 :             myAssert (curIndex < nd2x3);
     402               0 :             ib[curIndex] = bmap[i];
     403                 :             /* Check if we are supposed to insert xmissp into the field */
     404               0 :             if ((iclean != 0) && (ib[curIndex] == 0)) {
     405               0 :                iain[i] = xmissp;
     406                 :             } else {
     407               0 :                iain[curIndex] = fld[i];
     408                 :             }
     409                 :          }
     410                 :       } else {
     411               0 :          for (i = 0; i < ngrdpts; i++) {
     412               0 :             ScanIndex2XY (i, &x, &y, *scan, nx, ny);
     413                 :             /* ScanIndex returns value as if scan was 0100(0000) */
     414               0 :             curIndex = (x - 1) + (y - 1) * nx;
     415               0 :             myAssert (curIndex < nd2x3);
     416               0 :             iain[curIndex] = fld[i];
     417                 :          }
     418                 :       }
     419               0 :       *scan = 64 + (*scan & 0x0f);
     420                 :    }
     421               0 :    return 0;
     422                 : }
     423                 : 
     424                 : /*****************************************************************************
     425                 :  * TransferFloat() --
     426                 :  *
     427                 :  * Arthur Taylor / MDL
     428                 :  *
     429                 :  * PURPOSE
     430                 :  *   To transfer the data from "fld" and "bmap" to "ain" and "ib".  The API
     431                 :  * attempts to rearrange the order, so that anything returned from it has
     432                 :  * scan mode 0100????
     433                 :  *
     434                 :  * ARGUMENTS
     435                 :  *          fld = The expanded grid from NCEPs routines (Input)
     436                 :  *      ngrdpts = Length of fld (Input)
     437                 :  *      ibitmap = flag if we have a bitmap or not. (Input)
     438                 :  *         bmap = bitmap from NCEPs routines. (Input)
     439                 :  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
     440                 :  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
     441                 :  *       nx, ny = The dimmensions of the grid. (Input)
     442                 :  *       iclean = 1 means the user wants the unpacked data returned without
     443                 :  *                missing values in it. 0 means embed the missing values. (In)
     444                 :  *       xmissp = The primary missing value to use if iclean = 0. (Input).
     445                 :  *          ain = The grid to return. (Output)
     446                 :  *        nd2x3 = The length of iain. (Input)
     447                 :  *           ib = Bitmap if it was packed (Output)
     448                 :  *
     449                 :  * FILES/DATABASES: None
     450                 :  *
     451                 :  * RETURNS: int
     452                 :  *  0 = Ok.
     453                 :  *  1 = nd2x3 is too small.
     454                 :  *  2 = nx*ny != ngrdpts
     455                 :  *
     456                 :  * HISTORY
     457                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     458                 :  *
     459                 :  * NOTES
     460                 :  *   May want to disable the scan adjustment in the future.
     461                 :  *****************************************************************************
     462                 :  */
     463               2 : static int TransferFloat (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
     464                 :                           sInt4 * bmap, char f_ignoreScan, sInt4 * scan,
     465                 :                           sInt4 nx, sInt4 ny, sInt4 iclean, float xmissp,
     466                 :                           float * ain, sInt4 nd2x3, sInt4 * ib)
     467                 : {
     468                 :    int i;               /* loop counter over all grid points. */
     469                 :    sInt4 x, y;       /* Where we are in a grid of scan value 0100???? */
     470                 :    int curIndex;        /* Where in ain to store the current data. */
     471                 : 
     472               2 :    if (nd2x3 < ngrdpts) {
     473                 : #ifdef DEBUG
     474               0 :       printf ("nd2x3(%d) is < ngrdpts(%d)\n", nd2x3, ngrdpts);
     475                 : #endif
     476               0 :       return 1;
     477                 :    }
     478               2 :    if (f_ignoreScan || ((*scan & 0xf0) == 64)) {
     479               0 :       if (ibitmap) {
     480               0 :          for (i = 0; i < ngrdpts; i++) {
     481               0 :             ib[i] = bmap[i];
     482                 :             /* Check if we are supposed to insert xmissp into the field */
     483               0 :             if ((iclean != 0) && (ib[i] == 0)) {
     484               0 :                ain[i] = xmissp;
     485                 :             } else {
     486               0 :                ain[i] = fld[i];
     487                 :             }
     488                 :          }
     489                 :       } else {
     490               0 :          for (i = 0; i < ngrdpts; i++) {
     491               0 :             ain[i] = fld[i];
     492                 :          }
     493                 :       }
     494                 :    } else {
     495               2 :       if (nx * ny != ngrdpts) {
     496                 : #ifdef DEBUG
     497               0 :          printf ("nx * ny (%d) != ngrdpts(%d)\n", nx * ny, ngrdpts);
     498                 : #endif
     499               0 :          return 2;
     500                 :       }
     501               2 :       if (ibitmap) {
     502               0 :          for (i = 0; i < ngrdpts; i++) {
     503               0 :             ScanIndex2XY (i, &x, &y, *scan, nx, ny);
     504                 :             /* ScanIndex returns value as if scan was 0100(0000) */
     505               0 :             curIndex = (x - 1) + (y - 1) * nx;
     506               0 :             myAssert (curIndex < nd2x3);
     507               0 :             ib[curIndex] = bmap[i];
     508                 :             /* Check if we are supposed to insert xmissp into the field */
     509               0 :             if ((iclean != 0) && (ib[curIndex] == 0)) {
     510               0 :                ain[i] = xmissp;
     511                 :             } else {
     512               0 :                ain[curIndex] = fld[i];
     513                 :             }
     514                 :          }
     515                 :       } else {
     516           45668 :          for (i = 0; i < ngrdpts; i++) {
     517           45666 :             ScanIndex2XY (i, &x, &y, *scan, nx, ny);
     518                 :             /* ScanIndex returns value as if scan was 0100(0000) */
     519           45666 :             curIndex = (x - 1) + (y - 1) * nx;
     520           45666 :             myAssert (curIndex < nd2x3);
     521           45666 :             ain[curIndex] = fld[i];
     522                 :          }
     523                 :       }
     524               2 :       *scan = 64 + (*scan & 0x0f);
     525                 :    }
     526                 : /*
     527                 :    if (1==1) {
     528                 :       int i;
     529                 :       for (i=0; i < ngrdpts; i++) {
     530                 :          if (ain[i] != 9999) {
     531                 :             fprintf (stderr, "grib2api.c: ain[%d] %f, fld[%d] %f\n", i, ain[i],
     532                 :                      i, fld[i]);
     533                 :          }
     534                 :       }
     535                 :    }
     536                 : */
     537               2 :    return 0;
     538                 : }
     539                 : 
     540                 : #ifdef PKNCEP
     541                 : int pk_g2ncep (sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nx,
     542                 :                sInt4 * ny, sInt4 * idat, sInt4 * nidat, float * rdat,
     543                 :                sInt4 * nrdat, sInt4 * is0, sInt4 * ns0, sInt4 * is1,
     544                 :                sInt4 * ns1, sInt4 * is3, sInt4 * ns3, sInt4 * is4,
     545                 :                sInt4 * ns4, sInt4 * is5, sInt4 * ns5, sInt4 * is6,
     546                 :                sInt4 * ns6, sInt4 * is7, sInt4 * ns7, sInt4 * ib,
     547                 :                sInt4 * ibitmap, unsigned char *cgrib, sInt4 * nd5,
     548                 :                sInt4 * missp, float * xmissp, sInt4 * misss,
     549                 :                float * xmisss, sInt4 * inew, sInt4 * minpk, sInt4 * iclean,
     550                 :                sInt4 * l3264b, sInt4 * jer, sInt4 * ndjer, sInt4 * kjer)
     551                 : {
     552                 :    g2int listsec0[2];
     553                 :    g2int listsec1[13];
     554                 :    g2int igds[5];
     555                 :    g2int igdstmpl[];
     556                 :    int ierr;            /* Holds the error code from a called routine. */
     557                 :    int i;
     558                 : 
     559                 :    listsec0[0] = is0[6];
     560                 :    listsec0[1] = is0[7];
     561                 : 
     562                 :    listsec1[0] = is1[5];
     563                 :    listsec1[1] = is1[7];
     564                 :    listsec1[2] = is1[9];
     565                 :    listsec1[3] = is1[10];
     566                 :    listsec1[4] = is1[11];
     567                 :    listsec1[5] = is1[12];
     568                 :    listsec1[6] = is1[14];
     569                 :    listsec1[7] = is1[15];
     570                 :    listsec1[8] = is1[16];
     571                 :    listsec1[9] = is1[17];
     572                 :    listsec1[10] = is1[18];
     573                 :    listsec1[11] = is1[19];
     574                 :    listsec1[12] = is1[20];
     575                 : 
     576                 :    ierr = g2_create (cgrib, listsec0, listsec1);
     577                 :    printf ("Length = %d\n", ierr);
     578                 : 
     579                 :    if ((idat[0] != 0) || (rdat[0] != 0)) {
     580                 :       printf ("Don't handle this yet.\n");
     581                 : /*
     582                 :       ierr = g2_addlocal (cgrib, unsigned char *csec2, g2int lcsec2);
     583                 : */
     584                 :    }
     585                 : 
     586                 :    igds[0] = is3[5];
     587                 :    igds[1] = is3[6];
     588                 :    igds[2] = is3[10];
     589                 :    igds[3] = is3[11];
     590                 :    igds[4] = is3[12];
     591                 : 
     592                 : IS3(15) -  IS3(nn) = Grid Definition Template, stored in bytes 15-nn (*)
     593                 : 
     594                 :    ierr = g2_addgrid (cgrib, igds, g2int *igdstmpl, g2int *ideflist,
     595                 :                       g2int idefnum)
     596                 : 
     597                 : 
     598                 : 
     599                 : 
     600                 :    return 0;
     601                 : /*
     602                 : 
     603                 : To start a new GRIB2 message, call function g2_create.  G2_create
     604                 : encodes Sections 0 and 1 at the beginning of the message.  This routine
     605                 : must be used to create each message.
     606                 : 
     607                 : Routine g2_addlocal can be used to add a Local Use Section ( Section 2 ).
     608                 : Note that this section is optional and need not appear in a GRIB2 message.
     609                 : 
     610                 : Function g2_addgrid is used to encode a grid definition into Section 3.
     611                 : This grid definition defines the geometry of the the data values in the
     612                 : fields that follow it.  g2_addgrid can be called again to change the grid
     613                 : definition describing subsequent data fields.
     614                 : 
     615                 : Each data field is added to the GRIB2 message using routine g2_addfield,
     616                 : which adds Sections 4, 5, 6, and 7 to the message.
     617                 : 
     618                 : After all desired data fields have been added to the GRIB2 message, a
     619                 : call to function g2_gribend is needed to add the final section 8 to the
     620                 : message and to update the length of the message.  A call to g2_gribend
     621                 : is required for each GRIB2 message.
     622                 : */
     623                 : 
     624                 : }
     625                 : #endif
     626                 : 
     627                 : /*****************************************************************************
     628                 :  * unpk_g2ncep() --
     629                 :  *
     630                 :  * Arthur Taylor / MDL
     631                 :  *
     632                 :  * PURPOSE
     633                 :  *   This procedure is a wrapper around the NCEP GRIB2 routines to interface
     634                 :  * their routines with the "official NWS" GRIB2 API.  The reason for this is
     635                 :  * so drivers that have been written to use the "official NWS" GRIB2 API, can
     636                 :  * use the NCEP library with minimal disruption.
     637                 :  *
     638                 :  * ARGUMENTS
     639                 :  *  kfildo = Unit number for output diagnostics (C ignores this). (Input)
     640                 :  *     ain = contains the data if the original data was float data.
     641                 :  *           (size = nd2x3) (Output)
     642                 :  *    iain = contains the data if the original data was integer data.
     643                 :  *           (size = nd2x3) (Output)
     644                 :  *   nd2x3 = length of ain, iain, ib (Input)
     645                 :  *           (at least the size of num grid points)
     646                 :  *    idat = local use data if any that were unpacked from Section 2. (Output)
     647                 :  *   nidat = length of idat. (Input)
     648                 :  *    rdat = floating point local use data (Output)
     649                 :  *   nrdat = length of rdat. (Input)
     650                 :  *     is0 = Section 0 data (Output)
     651                 :  *     ns0 = length of is0 (16 is fine) (Input)
     652                 :  *     is1 = Section 1 data (Output)
     653                 :  *     ns1 = length of is1 (21 is fine) (Input)
     654                 :  *     is2 = Section 2 data (Output)
     655                 :  *     ns2 = length of is2 () (Input)
     656                 :  *     is3 = Section 3 data (Output)
     657                 :  *     ns3 = length of is3 (96 or 1600) (Input)
     658                 :  *     is4 = Section 4 data (Output)
     659                 :  *     ns4 = length of is4 (60) (Input)
     660                 :  *     is5 = Section 5 data (Output)
     661                 :  *     ns5 = length of is5 (49 is fine) (Input)
     662                 :  *     is6 = Section 6 data (Output)
     663                 :  *     ns6 = length of is6 (6 is fine) (Input)
     664                 :  *     is7 = Section 7 data (Output)
     665                 :  *     ns7 = length of is7 (8 is fine) (Input)
     666                 :  *      ib = Bitmap if user requested it, and it was packed (Output)
     667                 :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Output)
     668                 :  * c_ipack = The message to unpack (Input)
     669                 :  *     nd5 = 1/4 the size of c_ipack (Input)
     670                 :  *  xmissp = The floating point representation for the primary missing value.
     671                 :  *           (Input/Output)
     672                 :  *  xmisss = The floating point representation for the secondary missing
     673                 :  *           value (Input/Output)
     674                 :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
     675                 :  *  iclean = 1 means the user wants the unpacked data returned without
     676                 :  *           missing values in it. 0 means embed the missing values. (Input)
     677                 :  *  l3264b = Integer word length in bits (32 or 64) (Input)
     678                 :  *  iendpk = A 1 means no more grids in this message, a 0 means more grids.
     679                 :  *           (Output)
     680                 :  * jer(ndjer,2) = error codes along with severity. (Output)
     681                 :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
     682                 :  *    kjer = number of error messages stored in jer.
     683                 :  *
     684                 :  * FILES/DATABASES: None
     685                 :  *
     686                 :  * RETURNS: void
     687                 :  *   "jer" is used to store error messages, and kjer is used to denote how
     688                 :  * many there were.  Jer is set up as a 2 column array, with the first
     689                 :  * column in the first half of the array, and denoting the GRIB2 section
     690                 :  * an error occurred in.  The second column denoting the severity.
     691                 :  *
     692                 :  *    The possibilities from unpk_g2ncep() are as follows:
     693                 :  * ker=1 jer[0,0]=0    jer[0,1]=2: Message is not formed correctly
     694                 :  *                                 Request for an invalid subgrid
     695                 :  *                                 Problems unpacking the data.
     696                 :  *                                 problems expanding the data.
     697                 :  *                                 Calling dimmensions were too small.
     698                 :  * ker=2 jer[1,0]=100  jer[1,1]=2: Error unpacking section 1.
     699                 :  * ker=3 jer[2,0]=200  jer[2,1]=2: Error unpacking section 2.
     700                 :  * ker=4 jer[3,0]=300  jer[3,1]=2: Error unpacking section 3.
     701                 :  * ker=5 jer[4,0]=400  jer[4,1]=2: Error unpacking section 4.
     702                 :  * ker=6 jer[5,0]=500  jer[5,1]=2: Error unpacking section 5.
     703                 :  *                                 Data Template not implemented.
     704                 :  *                                 Durring Transfer, nx * ny != ngrdpts.
     705                 :  * ker=7 jer[6,0]=600  jer[6,1]=2: Error unpacking section 6.
     706                 :  * ker=8 jer[7,0]=700  jer[7,1]=2: Error unpacking section 7.
     707                 :  * ker=9 jer[8,0]=2001 jer[8,1]=2: nd2x3 is not large enough.
     708                 :  * ker=9 jer[8,0]=2003 jer[8,1]=2: undefined sect 3 template
     709                 :  *                                 (see gridtemplates.h).
     710                 :  * ker=9 jer[8,0]=2004 jer[8,1]=2: undefined sect 4 template
     711                 :  *                                 (see pdstemplates.h).
     712                 :  * ker=9 jer[8,0]=2005 jer[8,1]=2: undefined sect 5 template
     713                 :  *                                 (see drstemplates.h).
     714                 :  * ker=9 jer[8,0]=9999 jer[8,1]=2: NCEP returns an unrecognized error.
     715                 :  *
     716                 :  * HISTORY
     717                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
     718                 :  *
     719                 :  * NOTES
     720                 :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
     721                 :  * MDL attempts to always return grids in scan mode 0100????
     722                 :  *
     723                 :  * ToDo: Check length of parameters better.
     724                 :  * ToDo: Probably shouldn't abort if they have problems expanding the data.
     725                 :  * ToDo: Better handling of:
     726                 :  * gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array contains
     727                 :  *      the number of grid points contained in each row (or column). (part of
     728                 :  *      Section 3)  This element is a pointer to an array that holds the data.
     729                 :  *      This pointer is nullified if gfld->numoct_opt=0.
     730                 :  * gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)  The number of entries in
     731                 :  *      array ideflist.  i.e. number of rows (or columns) for which optional
     732                 :  *      grid points are defined.  This value is set to zero, if
     733                 :  *      gfld->numoct_opt=0.
     734                 :  * gfld->coord_list  = Real array containing floating point values intended to
     735                 :  *      document the vertical discretisation associated to model data on
     736                 :  *      hybrid coordinate vertical levels.  (part of Section 4) This element
     737                 :  *      is a pointer to an array that holds the data.
     738                 :  * gfld->num_coord = number of values in array gfld->coord_list[].
     739                 :  *****************************************************************************
     740                 :  */
     741               2 : void unpk_g2ncep (sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nd2x3,
     742                 :                   sInt4 * idat, sInt4 * nidat, float * rdat, sInt4 * nrdat,
     743                 :                   sInt4 * is0, sInt4 * ns0, sInt4 * is1, sInt4 * ns1,
     744                 :                   sInt4 * is2, sInt4 * ns2, sInt4 * is3, sInt4 * ns3,
     745                 :                   sInt4 * is4, sInt4 * ns4, sInt4 * is5, sInt4 * ns5,
     746                 :                   sInt4 * is6, sInt4 * ns6, sInt4 * is7, sInt4 * ns7,
     747                 :                   sInt4 * ib, sInt4 * ibitmap, unsigned char *c_ipack,
     748                 :                   sInt4 * nd5, float * xmissp, float * xmisss,
     749                 :                   sInt4 * inew, sInt4 * iclean, sInt4 * l3264b,
     750                 :                   sInt4 * iendpk, sInt4 * jer, sInt4 * ndjer, sInt4 * kjer)
     751                 : {
     752                 :    int i;               /* A counter used for a number of purposes. */
     753                 :    static unsigned int subgNum = 0; /* The sub grid we read most recently.
     754                 :                                      * This is primarily to help with the
     755                 :                                      * inew option. */
     756                 :    int ierr;            /* Holds the error code from a called routine. */
     757                 :    sInt4 listsec0[3];
     758                 :    sInt4 listsec1[13];
     759                 :    static sInt4 numfields = 1; /* Number of sub Grids in this message */
     760                 :    sInt4 numlocal;      /* Number of local sections in this message. */
     761                 :    int unpack;          /* Tell g2_getfld to unpack the message. */
     762                 :    int expand;          /* Tell g2_getflt to attempt to expand the bitmap. */
     763                 :    gribfield *gfld;     /* Holds the data after g2_getfld unpacks it. */
     764                 :    sInt4 gridIndex;     /* index in templatesgrid[] for this sect 3 templat */
     765                 :    sInt4 pdsIndex;      /* index in templatespds[] for this sect 4 template */
     766                 :    sInt4 drsIndex;      /* index in templatesdrs[] for this sect 5 template */
     767                 :    int curIndex;        /* Where in is3, is4, or is5 to store meta data */
     768                 :    int scanIndex;       /* Where in is3 to find the scan mode. */
     769                 :    int nxIndex;         /* Where in is3 to find the number of x values. */
     770                 :    int nyIndex;         /* Where in is3 to find the number of y values. */
     771                 :    float f_temp;       /* Assist with handling weird MDL behavior in is5[] */
     772                 :    char f_ignoreScan;   /* Flag to ignore the attempt at changing the scan */
     773                 :    sInt4 dummyScan;     /* Dummy place holder for call to Transfer routines
     774                 :                          * if ignoring scan. */
     775                 : 
     776               2 :    myAssert (*ndjer >= 8);
     777                 :    /* Init the error handling array. */
     778               2 :    memset ((void *) jer, 0, 2 * *ndjer * sizeof (sInt4));
     779              18 :    for (i = 0; i < 8; i++) {
     780              16 :       jer[i] = i * 100;
     781                 :    }
     782               2 :    *kjer = 8;
     783                 : 
     784                 :    /* The first time in, figure out how many grids there are, and store it
     785                 :     * in numfields for subsequent calls with inew != 1. */
     786               2 :    if (*inew == 1) {
     787               2 :       subgNum = 0;
     788               2 :       ierr = g2_info (c_ipack, listsec0, listsec1, &numfields, &numlocal);
     789               2 :       if (ierr != 0) {
     790               0 :          switch (ierr) {
     791                 :             case 1:    /* Beginning characters "GRIB" not found. */
     792                 :             case 2:    /* GRIB message is not Edition 2. */
     793                 :             case 3:    /* Could not find Section 1, where expected. */
     794                 :             case 4:    /* End string "7777" found, but not where expected. */
     795                 :             case 5:    /* End string "7777" not found at end of message. */
     796                 :             case 6:    /* Invalid section number found. */
     797               0 :                jer[0 + *ndjer] = 2;
     798               0 :                *kjer = 1;
     799               0 :                break;
     800                 :             default:
     801               0 :                jer[8 + *ndjer] = 2;
     802               0 :                jer[8] = 9999; /* Unknown error message. */
     803               0 :                *kjer = 9;
     804                 :          }
     805               0 :          return;
     806                 :       }
     807                 :    } else {
     808               0 :       if (subgNum + 1 >= numfields) {
     809                 :          /* Field request error. */
     810               0 :          jer[0 + *ndjer] = 2;
     811               0 :          *kjer = 1;
     812               0 :          return;
     813                 :       }
     814               0 :       subgNum++;
     815                 :    }
     816                 : 
     817                 :    /* Expand the desired subgrid. */
     818               2 :    unpack = 1;
     819               2 :    expand = 1;
     820               2 :    ierr = g2_getfld (c_ipack, subgNum + 1, unpack, expand, &gfld);
     821               2 :    if (ierr != 0) {
     822               0 :       switch (ierr) {
     823                 :          case 1:       /* Beginning characters "GRIB" not found. */
     824                 :          case 2:       /* GRIB message is not Edition 2. */
     825                 :          case 3:       /* The data field request number was not positive. */
     826                 :          case 4:       /* End string "7777" found, but not where expected. */
     827                 :          case 6:       /* message did not contain requested # of fields */
     828                 :          case 7:       /* End string "7777" not found at end of message. */
     829                 :          case 8:       /* Unrecognized Section encountered. */
     830               0 :             jer[0 + *ndjer] = 2;
     831               0 :             *kjer = 1;
     832               0 :             break;
     833                 :          case 15:      /* Error unpacking Section 1. */
     834               0 :             jer[1 + *ndjer] = 2;
     835               0 :             *kjer = 2;
     836               0 :             break;
     837                 :          case 16:      /* Error unpacking Section 2. */
     838               0 :             jer[2 + *ndjer] = 2;
     839               0 :             *kjer = 3;
     840               0 :             break;
     841                 :          case 10:      /* Error unpacking Section 3. */
     842               0 :             jer[3 + *ndjer] = 2;
     843               0 :             *kjer = 4;
     844               0 :             break;
     845                 :          case 11:      /* Error unpacking Section 4. */
     846               0 :             jer[4 + *ndjer] = 2;
     847               0 :             *kjer = 5;
     848               0 :             break;
     849                 :          case 9:       /* Data Template 5.NN not implemented. */
     850                 :          case 12:      /* Error unpacking Section 5. */
     851               0 :             jer[5 + *ndjer] = 2;
     852               0 :             *kjer = 6;
     853               0 :             break;
     854                 :          case 13:      /* Error unpacking Section 6. */
     855               0 :             jer[6 + *ndjer] = 2;
     856               0 :             *kjer = 7;
     857               0 :             break;
     858                 :          case 14:      /* Error unpacking Section 7. */
     859               0 :             jer[7 + *ndjer] = 2;
     860               0 :             *kjer = 8;
     861               0 :             break;
     862                 :          default:
     863               0 :             jer[8 + *ndjer] = 2;
     864               0 :             jer[8] = 9999; /* Unknown error message. */
     865               0 :             *kjer = 9;
     866                 :             break;
     867                 :       }
     868               0 :       g2_free (gfld);
     869               0 :       return;
     870                 :    }
     871                 :    /* Check if data wasn't unpacked. */
     872               2 :    if (!gfld->unpacked) {
     873               0 :       jer[0 + *ndjer] = 2;
     874               0 :       *kjer = 1;
     875               0 :       g2_free (gfld);
     876               0 :       return;
     877                 :    }
     878                 : 
     879                 :    /* Start going through the gfld structure and converting it to the needed
     880                 :     * data output formats. */
     881               2 :    myAssert (*ns0 >= 16);
     882               2 :    MEMCPY_BIG (&(is0[0]), c_ipack, sizeof (sInt4));
     883               2 :    is0[6] = gfld->discipline;
     884               2 :    is0[7] = gfld->version;
     885               2 :    MEMCPY_BIG (&(is0[8]), c_ipack + 8, sizeof (sInt4));
     886                 :    /* The following assert fails only if the GRIB message is more that 4
     887                 :     * giga-bytes large, which I think would break the fortran library. */
     888               2 :    myAssert (is0[8] == 0);
     889               2 :    MEMCPY_BIG (&(is0[8]), c_ipack + 12, sizeof (sInt4));
     890                 : 
     891               2 :    myAssert (*ns1 >= 21);
     892               2 :    myAssert (gfld->idsectlen >= 13);
     893               2 :    MEMCPY_BIG (&(is1[0]), c_ipack + 16, sizeof (sInt4));
     894               2 :    is1[4] = c_ipack[20];
     895               2 :    is1[5] = gfld->idsect[0];
     896               2 :    is1[7] = gfld->idsect[1];
     897               2 :    is1[9] = gfld->idsect[2];
     898               2 :    is1[10] = gfld->idsect[3];
     899               2 :    is1[11] = gfld->idsect[4];
     900               2 :    is1[12] = gfld->idsect[5]; /* Year */
     901               2 :    is1[14] = gfld->idsect[6]; /* Month */
     902               2 :    is1[15] = gfld->idsect[7]; /* Day */
     903               2 :    is1[16] = gfld->idsect[8]; /* Hour */
     904               2 :    is1[17] = gfld->idsect[9]; /* Min */
     905               2 :    is1[18] = gfld->idsect[10]; /* Sec */
     906               2 :    is1[19] = gfld->idsect[11];
     907               2 :    is1[20] = gfld->idsect[12];
     908                 : 
     909                 :    /* Fill out section lengths (separate procedure because of possibility of
     910                 :     * having multiple grids.  Should combine fillOutSectLen g2_info, and
     911                 :     * g2_getfld into one procedure to optimize it. */
     912               2 :    fillOutSectLen (c_ipack + 16 + is1[0], 4 * *nd5 - 15 - is1[0], subgNum,
     913                 :                    is2, is3, is4, is5, is6, is7);
     914                 : 
     915                 :    /* Check if there is section 2 data. */
     916               2 :    if (gfld->locallen > 0) {
     917                 :       /* The + 1 is so we don't overwrite the section length */
     918               0 :       memset ((void *) (is2 + 1), 0, (*ns2 - 1) * sizeof (sInt4));
     919               0 :       is2[4] = 2;
     920               0 :       is2[5] = gfld->local[0];
     921                 :       /* check if MDL Local use simple packed data */
     922               0 :       if (is2[5] == 1) {
     923               0 :          mdl_LocalUnpack (gfld->local, gfld->locallen, idat, nidat,
     924                 :                           rdat, nrdat);
     925                 :       } else {
     926                 :          /* local use section was not MDL packed, return it in is2. */
     927               0 :          for (i = 0; i < gfld->locallen; i++) {
     928               0 :             is2[i + 5] = gfld->local[i];
     929                 :          }
     930                 :       }
     931                 :    } else {
     932                 :       /* API specified that is2[0] = 0; idat[0] = 0, and rdat[0] = 0 */
     933               2 :       is2[0] = 0;
     934               2 :       idat[0] = 0;
     935               2 :       rdat[0] = 0;
     936                 :    }
     937                 : 
     938               2 :    is3[4] = 3;
     939               2 :    is3[5] = gfld->griddef;
     940               2 :    is3[6] = gfld->ngrdpts;
     941               2 :    if (*nd2x3 < gfld->ngrdpts) {
     942               0 :       jer[8 + *ndjer] = 2;
     943               0 :       jer[8] = 2001;    /* nd2x3 is not large enough */
     944               0 :       *kjer = 9;
     945               0 :       g2_free (gfld);
     946               0 :       return;
     947                 :    }
     948               2 :    is3[10] = gfld->numoct_opt;
     949               2 :    is3[11] = gfld->interp_opt;
     950               2 :    is3[12] = gfld->igdtnum;
     951               2 :    gridIndex = getgridindex (gfld->igdtnum);
     952               2 :    if (gridIndex == -1) {
     953               0 :       jer[8 + *ndjer] = 2;
     954               0 :       jer[8] = 2003;    /* undefined sect 3 template */
     955               0 :       *kjer = 9;
     956               0 :       g2_free (gfld);
     957               0 :       return;
     958                 :    }
     959               2 :    curIndex = 14;
     960              40 :    for (i = 0; i < gfld->igdtlen; i++) {
     961              38 :       const struct gridtemplate *templatesgrid = get_templatesgrid();
     962              38 :       is3[curIndex] = gfld->igdtmpl[i];
     963              38 :       curIndex += abs (templatesgrid[gridIndex].mapgrid[i]);
     964                 :    }
     965                 :    /* API attempts to return grid in scan mode 0100????.  Find the necessary
     966                 :     * indexes into the is3 array for the attempt. */
     967               2 :    switch (gfld->igdtnum) {
     968                 :       case 0:
     969                 :       case 1:
     970                 :       case 2:
     971                 :       case 3:
     972                 :       case 40:
     973                 :       case 41:
     974                 :       case 42:
     975                 :       case 43:
     976               0 :          scanIndex = 72 - 1;
     977               0 :          nxIndex = 31 - 1;
     978               0 :          nyIndex = 35 - 1;
     979               0 :          break;
     980                 :       case 10:
     981               2 :          scanIndex = 60 - 1;
     982               2 :          nxIndex = 31 - 1;
     983               2 :          nyIndex = 35 - 1;
     984               2 :          break;
     985                 :       case 20:
     986                 :       case 30:
     987                 :       case 31:
     988               0 :          scanIndex = 65 - 1;
     989               0 :          nxIndex = 31 - 1;
     990               0 :          nyIndex = 35 - 1;
     991               0 :          break;
     992                 :       case 90:
     993               0 :          scanIndex = 64 - 1;
     994               0 :          nxIndex = 31 - 1;
     995               0 :          nyIndex = 35 - 1;
     996               0 :          break;
     997                 :       case 110:
     998               0 :          scanIndex = 57 - 1;
     999               0 :          nxIndex = 31 - 1;
    1000               0 :          nyIndex = 35 - 1;
    1001               0 :          break;
    1002                 :       case 50:
    1003                 :       case 51:
    1004                 :       case 52:
    1005                 :       case 53:
    1006                 :       case 100:
    1007                 :       case 120:
    1008                 :       case 1000:
    1009                 :       case 1200:
    1010                 :       default:
    1011               0 :          scanIndex = -1;
    1012               0 :          nxIndex = -1;
    1013               0 :          nyIndex = -1;
    1014                 :    }
    1015                 : 
    1016               2 :    is4[4] = 4;
    1017               2 :    is4[5] = gfld->num_coord;
    1018               2 :    is4[7] = gfld->ipdtnum;
    1019               2 :    pdsIndex = getpdsindex (gfld->ipdtnum);
    1020               2 :    if (pdsIndex == -1) {
    1021               0 :       jer[8 + *ndjer] = 2;
    1022               0 :       jer[8] = 2004;    /* undefined sect 4 template */
    1023               0 :       *kjer = 9;
    1024               0 :       g2_free (gfld);
    1025               0 :       return;
    1026                 :    }
    1027               2 :    curIndex = 9;
    1028              60 :    for (i = 0; i < gfld->ipdtlen; i++) {
    1029              58 :       const struct pdstemplate *templatespds = get_templatespds();
    1030              58 :       is4[curIndex] = gfld->ipdtmpl[i];
    1031              58 :       curIndex += abs (templatespds[pdsIndex].mappds[i]);
    1032                 :    }
    1033                 : 
    1034               2 :    is5[4] = 5;
    1035               2 :    is5[5] = gfld->ndpts;
    1036               2 :    is5[9] = gfld->idrtnum;
    1037               2 :    drsIndex = getdrsindex (gfld->idrtnum);
    1038               2 :    if (drsIndex == -1) {
    1039               0 :       jer[8 + *ndjer] = 2;
    1040               0 :       jer[8] = 2005;    /* undefined sect 5 template */
    1041               0 :       *kjer = 9;
    1042               0 :       g2_free (gfld);
    1043               0 :       return;
    1044                 :    }
    1045               2 :    curIndex = 11;
    1046              38 :    for (i = 0; i < gfld->idrtlen; i++) {
    1047              36 :       const struct drstemplate *templatesdrs = get_templatesdrs();
    1048              36 :       is5[curIndex] = gfld->idrtmpl[i];
    1049              36 :       curIndex += abs (templatesdrs[drsIndex].mapdrs[i]);
    1050                 :    }
    1051                 :    /* Mimic MDL's handling of reference value (IS5(12)) */
    1052               2 :    memcpy (&f_temp, &(is5[11]), sizeof (float));
    1053               2 :    is5[11] = (sInt4) f_temp;
    1054               2 :    if ((is5[9] == 2) || (is5[9] == 3)) {
    1055               2 :       if (is5[20] == 0) {
    1056               2 :          memcpy (&(f_temp), &(is5[23]), sizeof (float));
    1057               2 :          *xmissp = f_temp;
    1058               2 :          is5[23] = (sInt4) f_temp;
    1059               2 :          memcpy (&(f_temp), &(is5[27]), sizeof (float));
    1060               2 :          *xmisss = f_temp;
    1061               2 :          is5[27] = (sInt4) f_temp;
    1062                 :       } else {
    1063               0 :          *xmissp = is5[23];
    1064               0 :          *xmisss = is5[27];
    1065                 :       }
    1066                 :    }
    1067                 : 
    1068               2 :    is6[4] = 6;
    1069               2 :    is6[5] = gfld->ibmap;
    1070               2 :    is7[4] = 7;
    1071                 : 
    1072               2 :    if (subgNum + 1 == numfields) {
    1073               2 :       *iendpk = 1;
    1074                 :    } else {
    1075               0 :       *iendpk = 0;
    1076                 :    }
    1077                 : 
    1078               2 :    if ((gfld->ibmap == 0) || (gfld->ibmap == 254)) {
    1079               0 :       *ibitmap = 1;
    1080                 :    } else {
    1081               2 :       *ibitmap = 0;
    1082                 :    }
    1083                 : 
    1084                 :    /* Check type of original field, before transfering the memory. */
    1085               2 :    myAssert (*ns5 > 20);
    1086                 :    /* Check if NCEP had problems expanding the data.  If so we currently
    1087                 :     * abort.  May need to revisit this behavior. */
    1088               2 :    if (!gfld->expanded) {
    1089               0 :       jer[0 + *ndjer] = 2;
    1090               0 :       *kjer = 1;
    1091               0 :       g2_free (gfld);
    1092               0 :       return;
    1093                 :    }
    1094               2 :    f_ignoreScan = 0;
    1095                 :    /* Check if integer type... is5[20] == 1 implies integer (code table
    1096                 :     * 5.1), but only for certain templates. (0,1,2,3,40,41,40000,40010).
    1097                 :     * (not 50,51) */
    1098               2 :    if ((is5[20] == 1) && ((is5[9] != 50) && (is5[9] != 51))) {
    1099                 :       /* integer data, use iain */
    1100               0 :       if ((scanIndex < 0) || (nxIndex < 0) || (nyIndex < 0)) {
    1101               0 :          ierr = TransferInt (gfld->fld, gfld->ngrdpts, *ibitmap, gfld->bmap,
    1102                 :                              1, &(dummyScan), 0, 0, *iclean, *xmissp,
    1103                 :                              iain, *nd2x3, ib);
    1104                 :       } else {
    1105               0 :          ierr = TransferInt (gfld->fld, gfld->ngrdpts, *ibitmap, gfld->bmap,
    1106               0 :                              f_ignoreScan, &(is3[scanIndex]), is3[nxIndex],
    1107               0 :                              is3[nyIndex], *iclean, *xmissp, iain, *nd2x3,
    1108                 :                              ib);
    1109                 :       }
    1110                 :    } else {
    1111                 :       /* float data, use ain */
    1112               2 :       if ((scanIndex < 0) || (nxIndex < 0) || (nyIndex < 0)) {
    1113               0 :          ierr = TransferFloat (gfld->fld, gfld->ngrdpts, *ibitmap,
    1114               0 :                                gfld->bmap, 1, &(dummyScan), 0, 0, *iclean,
    1115                 :                                *xmissp, ain, *nd2x3, ib);
    1116                 :       } else {
    1117              10 :          ierr = TransferFloat (gfld->fld, gfld->ngrdpts, *ibitmap,
    1118               4 :                                gfld->bmap, f_ignoreScan, &(is3[scanIndex]),
    1119               4 :                                is3[nxIndex], is3[nyIndex], *iclean, *xmissp,
    1120                 :                                ain, *nd2x3, ib);
    1121                 :       }
    1122                 :    }
    1123               2 :    if (ierr != 0) {
    1124               0 :       switch (ierr) {
    1125                 :          case 1:       /* nd2x3 is too small */
    1126               0 :             jer[0 + *ndjer] = 2;
    1127               0 :             *kjer = 1;
    1128               0 :             break;
    1129                 :          case 2:       /* nx * ny != ngrdpts */
    1130               0 :             jer[5 + *ndjer] = 2;
    1131               0 :             *kjer = 6;
    1132               0 :             break;
    1133                 :          default:
    1134               0 :             jer[8 + *ndjer] = 2;
    1135               0 :             jer[8] = 9999; /* Unknown error message. */
    1136               0 :             *kjer = 9;
    1137                 :       }
    1138               0 :       g2_free (gfld);
    1139               0 :       return;
    1140                 :    }
    1141               2 :    g2_free (gfld);
    1142                 : }
    1143                 : 
    1144                 : /*****************************************************************************
    1145                 :  * validate() --
    1146                 :  *
    1147                 :  * Arthur Taylor / MDL
    1148                 :  *
    1149                 :  * PURPOSE
    1150                 :  *   Output all the return values from the API to a file.  This is primarily
    1151                 :  * for diagnostics purposes.
    1152                 :  *
    1153                 :  * ARGUMENTS
    1154                 :  * filename = File to write the data to. (Input)
    1155                 :  *      ain = The data if the original data was float data. (nd2x3) (Input)
    1156                 :  *     iain = The data if the original data was integer data. (nd2x3) (Input)
    1157                 :  *    nd2x3 = length of ain, iain, ib (Input)
    1158                 :  *     idat = MDL local use data (if any were unpacked from Sect 2). (Input)
    1159                 :  *    nidat = length of idat. (Input)
    1160                 :  *     rdat = floating point local use data (Input)
    1161                 :  *    nrdat = length of rdat. (Input)
    1162                 :  * is0, ns0 = Section 0 data, length of is0 (16) (Input)
    1163                 :  * is1, ns1 = Section 1 data, length of is1 (21) (Input)
    1164                 :  * is2, ns2 = Section 2 data, length of is2 (??) (Input)
    1165                 :  * is3, ns3 = Section 3 data, length of is3 (96 or 1600) (Input)
    1166                 :  * is4, ns4 = Section 4 data, length of is4 (60) (Input)
    1167                 :  * is5, ns5 = Section 5 data, length of is5 (49) (Input)
    1168                 :  * is6, ns6 = Section 6 data, length of is6 (6) (Input)
    1169                 :  * is7, ns7 = Section 7 data, length of ns7 (8) (Input)
    1170                 :  *       ib = Bitmap if user requested it, and it was packed (Input)
    1171                 :  *  ibitmap = 0 means ib is invalid, 1 means ib is valid. (Input)
    1172                 :  *   xmissp = Primary missing value. (Input)
    1173                 :  *   xmisss = Secondary missing value (Input)
    1174                 :  *   iendpk = flag if there is more grids in the message. (Input)
    1175                 :  * jer(ndjer,2) = error codes along with severity. (Input)
    1176                 :  *    ndjer = length of jer. (15) (Input)
    1177                 :  *     kjer = number of error messages stored in jer. (Input)
    1178                 :  *
    1179                 :  * FILES/DATABASES: None
    1180                 :  *
    1181                 :  * RETURNS: int
    1182                 :  *  0 = Ok.
    1183                 :  * -1 = Problems opening the file.
    1184                 :  *
    1185                 :  * HISTORY
    1186                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1187                 :  *
    1188                 :  * NOTES
    1189                 :  *****************************************************************************
    1190                 :  */
    1191                 : #ifdef notdef
    1192                 : static int validate (char *filename, float * ain, sInt4 * iain,
    1193                 :                      sInt4 * nd2x3, sInt4 * idat, sInt4 * nidat,
    1194                 :                      float * rdat, sInt4 * nrdat, sInt4 * is0, sInt4 * ns0,
    1195                 :                      sInt4 * is1, sInt4 * ns1, sInt4 * is2, sInt4 * ns2,
    1196                 :                      sInt4 * is3, sInt4 * ns3, sInt4 * is4, sInt4 * ns4,
    1197                 :                      sInt4 * is5, sInt4 * ns5, sInt4 * is6, sInt4 * ns6,
    1198                 :                      sInt4 * is7, sInt4 * ns7, sInt4 * ib, sInt4 * ibitmap,
    1199                 :                      float * xmissp, float * xmisss, sInt4 * iendpk,
    1200                 :                      sInt4 * jer, sInt4 * ndjer, sInt4 * kjer)
    1201                 : {
    1202                 :    FILE *fp;            /* Open file to write to. */
    1203                 :    int i;               /* Counter for printing to file. */
    1204                 : 
    1205                 :    if ((fp = fopen (filename, "wt")) == NULL) {
    1206                 : #ifdef DEBUG
    1207                 :       printf ("unable to open %s for write\n", filename);
    1208                 : #endif
    1209                 :       return -1;
    1210                 :    }
    1211                 :    for (i = 0; i < *ns0; i++) {
    1212                 :       fprintf (fp, "Sect 0 : %d of %d : %d\n", i, *ns0, is0[i]);
    1213                 :    }
    1214                 :    for (i = 0; i < *ns1; i++) {
    1215                 :       fprintf (fp, "Sect 1 : %d of %d : %d\n", i, *ns1, is1[i]);
    1216                 :    }
    1217                 :    for (i = 0; i < *ns2; i++) {
    1218                 :       fprintf (fp, "Sect 2 : %d of %d : %d\n", i, *ns2, is2[i]);
    1219                 :    }
    1220                 :    for (i = 0; i < idat[0]; i++) {
    1221                 :       fprintf (fp, "idat : %d of %d : %d\n", i, idat[0], idat[i]);
    1222                 :    }
    1223                 :    for (i = 0; i < rdat[0]; i++) {
    1224                 :       fprintf (fp, "rdat : %d of %f : %f\n", i, rdat[0], rdat[i]);
    1225                 :    }
    1226                 :    for (i = 0; i < *ns3; i++) {
    1227                 :       fprintf (fp, "Sect 3 : %d of %d : %d\n", i, *ns3, is3[i]);
    1228                 :    }
    1229                 :    for (i = 0; i < *ns4; i++) {
    1230                 :       fprintf (fp, "Sect 4 : %d of %d : %d\n", i, *ns4, is4[i]);
    1231                 :    }
    1232                 :    for (i = 0; i < *ns5; i++) {
    1233                 :       fprintf (fp, "Sect 5 : %d of %d : %d\n", i, *ns5, is5[i]);
    1234                 :    }
    1235                 :    for (i = 0; i < *ns6; i++) {
    1236                 :       fprintf (fp, "Sect 6 : %d of %d : %d\n", i, *ns6, is6[i]);
    1237                 :    }
    1238                 :    for (i = 0; i < *ns7; i++) {
    1239                 :       fprintf (fp, "Sect 7 : %d of %d : %d\n", i, *ns7, is7[i]);
    1240                 :    }
    1241                 :    fprintf (fp, "Xmissp = %f\n", *xmissp);
    1242                 :    fprintf (fp, "xmisss = %f\n", *xmisss);
    1243                 :    if ((is5[9] == 0) || (is5[9] == 1) || (is5[9] == 2) || (is5[9] == 3)) {
    1244                 :       if (is5[20] == 1) {
    1245                 :          for (i = 0; i < *nd2x3; i++) {
    1246                 :             fprintf (fp, "Int Data : %d of %d : %d\n", i, *nd2x3, iain[i]);
    1247                 :          }
    1248                 :       }
    1249                 :    } else {
    1250                 :       for (i = 0; i < *nd2x3; i++) {
    1251                 :          fprintf (fp, "Float Data : %d of %d : %f\n", i, *nd2x3, ain[i]);
    1252                 :       }
    1253                 :    }
    1254                 :    fprintf (fp, "ibitmap = %d\n", *ibitmap);
    1255                 :    if (*ibitmap) {
    1256                 :       for (i = 0; i < *nd2x3; i++) {
    1257                 :          fprintf (fp, "Bitmap Data : %d of %d : %d\n", i, *nd2x3, ib[i]);
    1258                 :       }
    1259                 :    }
    1260                 :    for (i = 0; i < *ndjer; i++) {
    1261                 :       fprintf (fp, "jer(i,1) %d jer(i,2) %d\n", jer[i], jer[i + *ndjer]);
    1262                 :    }
    1263                 :    fprintf (fp, "kjer = %d\n", *kjer);
    1264                 :    fprintf (fp, "iendpk = %d\n", *iendpk);
    1265                 :    fclose (fp);
    1266                 :    return 0;
    1267                 : }
    1268                 : #endif /* def notdef */
    1269                 : 
    1270                 : /*****************************************************************************
    1271                 :  * clear() --
    1272                 :  *
    1273                 :  * Arthur Taylor / MDL
    1274                 :  *
    1275                 :  * PURPOSE
    1276                 :  *   Clear all the return values from the API.  This is primarily for
    1277                 :  * diagnostics purposes.
    1278                 :  *
    1279                 :  * ARGUMENTS
    1280                 :  *      ain = The data if the original data was float data. (nd2x3) (Output)
    1281                 :  *     iain = The data if the original data was integer data. (nd2x3) (Output)
    1282                 :  *    nd2x3 = length of ain, iain, ib (Input)
    1283                 :  *     idat = MDL local use data (if any were unpacked from Sect 2). (Output)
    1284                 :  *    nidat = length of idat. (Input)
    1285                 :  *     rdat = floating point local use data (Output)
    1286                 :  *    nrdat = length of rdat. (Input)
    1287                 :  * is0, ns0 = Section 0 data, length of is0 (16) (Output) (Input)
    1288                 :  * is1, ns1 = Section 1 data, length of is1 (21) (Output) (Input)
    1289                 :  * is2, ns2 = Section 2 data, length of is2 (??) (Output) (Input)
    1290                 :  * is3, ns3 = Section 3 data, length of is3 (96 or 1600) (Output) (Input)
    1291                 :  * is4, ns4 = Section 4 data, length of is4 (60) (Output) (Input)
    1292                 :  * is5, ns5 = Section 5 data, length of is5 (49) (Output) (Input)
    1293                 :  * is6, ns6 = Section 6 data, length of is6 (6) (Output) (Input)
    1294                 :  * is7, ns7 = Section 7 data, length of ns7 (8) (Output) (Input)
    1295                 :  *       ib = Bitmap if user requested it, and it was packed (Output)
    1296                 :  *  ibitmap = 0 means ib is invalid, 1 means ib is valid. (Output)
    1297                 :  *   xmissp = Primary missing value. (Output)
    1298                 :  *   xmisss = Secondary missing value (Output)
    1299                 :  *   iendpk = flag if there is more grids in the message. (Output)
    1300                 :  * jer(ndjer,2) = error codes along with severity. (Output)
    1301                 :  *    ndjer = length of jer. (15) (Input)
    1302                 :  *     kjer = number of error messages stored in jer. (Output)
    1303                 :  *
    1304                 :  * FILES/DATABASES: None
    1305                 :  *
    1306                 :  * RETURNS: int
    1307                 :  *  0 = Ok.
    1308                 :  * -1 = Problems opening the file.
    1309                 :  *
    1310                 :  * HISTORY
    1311                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1312                 :  *
    1313                 :  * NOTES
    1314                 :  *****************************************************************************
    1315                 :  */
    1316                 : /*
    1317                 : static void clear (float * ain, sInt4 * iain, sInt4 * nd2x3, sInt4 * idat,
    1318                 :                    sInt4 * nidat, float * rdat, sInt4 * nrdat, sInt4 * is0,
    1319                 :                    sInt4 * ns0, sInt4 * is1, sInt4 * ns1, sInt4 * is2,
    1320                 :                    sInt4 * ns2, sInt4 * is3, sInt4 * ns3, sInt4 * is4,
    1321                 :                    sInt4 * ns4, sInt4 * is5, sInt4 * ns5, sInt4 * is6,
    1322                 :                    sInt4 * ns6, sInt4 * is7, sInt4 * ns7, sInt4 * ib,
    1323                 :                    sInt4 * ibitmap, float * xmissp, float * xmisss,
    1324                 :                    sInt4 * iendpk, sInt4 * jer, sInt4 * ndjer, sInt4 * kjer)
    1325                 : {
    1326                 :    memset ((void *) ain, 0, *nd2x3 * sizeof (float));
    1327                 :    memset ((void *) iain, 0, *nd2x3 * sizeof (sInt4));
    1328                 :    memset ((void *) idat, 0, *nidat * sizeof (sInt4));
    1329                 :    memset ((void *) rdat, 0, *nrdat * sizeof (float));
    1330                 :    memset ((void *) is0, 0, *ns0 * sizeof (sInt4));
    1331                 :    memset ((void *) is1, 0, *ns1 * sizeof (sInt4));
    1332                 :    memset ((void *) is2, 0, *ns2 * sizeof (sInt4));
    1333                 :    memset ((void *) is3, 0, *ns3 * sizeof (sInt4));
    1334                 :    memset ((void *) is4, 0, *ns4 * sizeof (sInt4));
    1335                 :    if ((is5[9] == 2) || (is5[9] == 3)) {
    1336                 :       *xmissp = 0;
    1337                 :       *xmisss = 0;
    1338                 :    }
    1339                 :    memset ((void *) is5, 0, *ns5 * sizeof (sInt4));
    1340                 :    memset ((void *) is6, 0, *ns6 * sizeof (sInt4));
    1341                 :    memset ((void *) is7, 0, *ns7 * sizeof (sInt4));
    1342                 :    memset ((void *) ib, 0, *nd2x3 * sizeof (sInt4));
    1343                 :    *ibitmap = 0;
    1344                 :    *iendpk = 0;
    1345                 :    memset ((void *) jer, 0, 2 * *ndjer * sizeof (sInt4));
    1346                 :    *kjer = 0;
    1347                 : }
    1348                 : */
    1349                 : 
    1350                 : /*****************************************************************************
    1351                 :  * BigByteCpy() --
    1352                 :  *
    1353                 :  * Arthur Taylor / MDL
    1354                 :  *
    1355                 :  * PURPOSE
    1356                 :  *   This is so we can copy upto 4 bytes from a big endian 4 byte int data
    1357                 :  * stream.
    1358                 :  *
    1359                 :  *   The reason this is needed is because the GRIB2 API required the GRIB2
    1360                 :  * message to be passed in as a big endian 4 byte int data stream instead of
    1361                 :  * something more reasonable (such as a stream of 1 byte char's)  By having
    1362                 :  * this routine we reduce the number of memswaps of the message on a little
    1363                 :  * endian system.
    1364                 :  *
    1365                 :  * ARGUMENTS
    1366                 :  *       dst = Where to copy the data to. (Output)
    1367                 :  *     ipack = The 4 byte int data stream. (Input)
    1368                 :  *       nd5 = length of ipack (Input)
    1369                 :  *  startInt = Which integer to start reading in ipack. (Input)
    1370                 :  * startByte = Which byte in the startInt to start reading from. (Input)
    1371                 :  *   numByte = How many bytes to read. (Input)
    1372                 :  *
    1373                 :  * FILES/DATABASES: None
    1374                 :  *
    1375                 :  * RETURNS: NULL
    1376                 :  *
    1377                 :  * HISTORY
    1378                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1379                 :  *
    1380                 :  * NOTES
    1381                 :  *****************************************************************************
    1382                 :  */
    1383              32 : static void BigByteCpy (sInt4 * dst, sInt4 * ipack, sInt4 nd5,
    1384                 :                         unsigned int startInt, unsigned int startByte,
    1385                 :                         int numByte)
    1386                 : {
    1387                 :    static int Lshift[] = { 0, 8, 16, 24 }; /* Amounts to shift left by. */
    1388                 :    unsigned int intIndex; /* Where in ipack to read from. */
    1389                 :    unsigned int byteIndex; /* Where in intIndex to read from. */
    1390                 :    uInt4 curInt;        /* An unsigned version of the current int. */
    1391                 :    unsigned int curByte; /* The current byte we have read. */
    1392                 :    int i;               /* Loop counter over number of bytes to read. */
    1393                 : 
    1394              32 :    myAssert (numByte <= 4);
    1395              32 :    myAssert (startByte < 4);
    1396              32 :    *dst = 0;
    1397              32 :    intIndex = startInt;
    1398              32 :    byteIndex = startByte;
    1399             106 :    for (i = 0; i < numByte; i++) {
    1400              74 :       curInt = (uInt4) ipack[intIndex];
    1401              74 :       curByte = (curInt << Lshift[byteIndex]) >> 24;
    1402              74 :       *dst = (*dst << 8) + curByte;
    1403              74 :       byteIndex++;
    1404              74 :       if (byteIndex == 4) {
    1405              16 :          byteIndex = 0;
    1406              16 :          intIndex++;
    1407                 :       }
    1408                 :    }
    1409              32 : }
    1410                 : 
    1411                 : /*****************************************************************************
    1412                 :  * FindTemplateIDs() --
    1413                 :  *
    1414                 :  * Arthur Taylor / MDL
    1415                 :  *
    1416                 :  * PURPOSE
    1417                 :  *   This is so we can find out which templates are in this GRIB2 message.
    1418                 :  * Which allows us to determine if we can call the MDL routines, or if we
    1419                 :  * should call the NCEP routines instead.
    1420                 :  *
    1421                 :  * ARGUMENTS
    1422                 :  *      ipack = The 4 byte int data stream. (Input)
    1423                 :  *        nd5 = length of ipack (Input)
    1424                 :  *    subgNum = Which subgrid to look at. (Input)
    1425                 :  *    gdsTmpl = The gds template number for this subgrid. (Output)
    1426                 :  *    pdsTmpl = The pds template number for this subgrid. (Output)
    1427                 :  *    drsTmpl = The drs template number for this subgrid. (Output)
    1428                 :  * f_noBitmap = 0 has a bitmap, else doesn't have a bitmap. (Output)
    1429                 :  *  orderDiff = The order of the differencing in template 5.3 (1st, 2nd) (out)
    1430                 :  *
    1431                 :  * FILES/DATABASES: None
    1432                 :  *
    1433                 :  * RETURNS: int
    1434                 :  *  0 = Ok.
    1435                 :  *  2 = invalid section number
    1436                 :  *
    1437                 :  * HISTORY
    1438                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1439                 :  *
    1440                 :  * NOTES
    1441                 :  *****************************************************************************
    1442                 :  */
    1443               2 : static int FindTemplateIDs (sInt4 * ipack, sInt4 nd5, int subgNum,
    1444                 :                             sInt4 * gdsTmpl, sInt4 * pdsTmpl,
    1445                 :                             sInt4 * drsTmpl, sInt4 * numGrps,
    1446                 :                             uChar * f_noBitmap, sInt4 * orderDiff)
    1447                 : {
    1448               2 :    unsigned int gNum = 0; /* Which sub group we are currently working with. */
    1449                 :    sInt4 offset;        /* Where in the bytes stream we currently are. */
    1450                 :    sInt4 sectLen;       /* The length of the current section. */
    1451                 :    sInt4 sectId;        /* The current section number. */
    1452                 :    sInt4 li_temp;       /* A temporary holder for the bitmap flag. */
    1453                 : 
    1454                 :    /* Jump over section 0. */
    1455               2 :    offset = 16;
    1456              14 :    while (gNum <= subgNum) {
    1457              10 :       BigByteCpy (&sectLen, ipack, nd5, (offset / 4), (offset % 4), 4);
    1458                 :       /* Check if we just read section 8.  If so, then it is "7777" =
    1459                 :        * 926365495 regardless of endian'ness. */
    1460              10 :       if (sectLen == 926365495L) {
    1461                 : #ifdef DEBUG
    1462               0 :          printf ("Shouldn't see sect 8. Should stop after correct sect 5\n");
    1463                 : #endif
    1464               0 :          return 2;
    1465                 :       }
    1466              10 :       BigByteCpy (&sectId, ipack, nd5, ((offset + 4) / 4),
    1467              10 :                   ((offset + 4) % 4), 1);
    1468              10 :       switch (sectId) {
    1469                 :          case 1:
    1470                 :          case 2:
    1471               2 :             break;
    1472                 :          case 3:
    1473               2 :             BigByteCpy (gdsTmpl, ipack, nd5, ((offset + 12) / 4),
    1474               2 :                         ((offset + 12) % 4), 2);
    1475               2 :             break;
    1476                 :          case 4:
    1477               2 :             BigByteCpy (pdsTmpl, ipack, nd5, ((offset + 7) / 4),
    1478               2 :                         ((offset + 7) % 4), 2);
    1479               2 :             break;
    1480                 :          case 5:
    1481               2 :             BigByteCpy (drsTmpl, ipack, nd5, ((offset + 9) / 4),
    1482               2 :                         ((offset + 9) % 4), 2);
    1483               4 :             if ((*drsTmpl == 2) || (*drsTmpl == 3)) {
    1484               2 :                BigByteCpy (numGrps, ipack, nd5, ((offset + 31) / 4),
    1485               2 :                            ((offset + 31) % 4), 4);
    1486                 :             } else {
    1487               0 :                *numGrps = 0;
    1488                 :             }
    1489               2 :             if (*drsTmpl == 3) {
    1490               2 :                BigByteCpy (&li_temp, ipack, nd5, ((offset + 44) / 4),
    1491               2 :                            ((offset + 44) % 4), 1);
    1492               2 :                *orderDiff = li_temp;
    1493                 :             } else {
    1494               0 :                *orderDiff = 0;
    1495                 :             }
    1496               2 :             break;
    1497                 :          case 6:
    1498               2 :             BigByteCpy (&li_temp, ipack, nd5, ((offset + 5) / 4),
    1499               2 :                         ((offset + 5) % 4), 1);
    1500               2 :             if (li_temp == 255) {
    1501               2 :                *f_noBitmap = 1;
    1502                 :             }
    1503               2 :             gNum++;
    1504               2 :             break;
    1505                 :          case 7:
    1506               0 :             break;
    1507                 :          default:
    1508                 : #ifdef DEBUG
    1509               0 :             printf ("Invalid section id %d.\n", sectId);
    1510                 : #endif
    1511               0 :             return 2;
    1512                 :       }
    1513              10 :       offset += sectLen;
    1514                 :    }
    1515               2 :    return 0;
    1516                 : }
    1517                 : 
    1518                 : /*****************************************************************************
    1519                 :  * unpk_grib2() --
    1520                 :  *
    1521                 :  * Arthur Taylor / MDL
    1522                 :  *
    1523                 :  * PURPOSE
    1524                 :  *   This procedure is the main API for decoding GRIB2 messages.  It is
    1525                 :  * intended to be a branching routine to call either the MDL GRIB2 library,
    1526                 :  * or the NCEP GRIB2 library, depending on which template it sees in the
    1527                 :  * message.
    1528                 :  *
    1529                 :  * ARGUMENTS
    1530                 :  *  kfildo = Unit number for output diagnostics (C ignores this). (Input)
    1531                 :  *     ain = contains the data if the original data was float data.
    1532                 :  *           (size = nd2x3) (Output)
    1533                 :  *    iain = contains the data if the original data was integer data.
    1534                 :  *           (size = nd2x3) (Output)
    1535                 :  *   nd2x3 = length of ain, iain, ib (Input)
    1536                 :  *           (at least the size of num grid points)
    1537                 :  *    idat = local use data if any that were unpacked from Section 2. (Output)
    1538                 :  *   nidat = length of idat. (Input)
    1539                 :  *    rdat = floating point local use data (Output)
    1540                 :  *   nrdat = length of rdat. (Input)
    1541                 :  *     is0 = Section 0 data (Output)
    1542                 :  *     ns0 = length of is0 (16 is fine) (Input)
    1543                 :  *     is1 = Section 1 data (Output)
    1544                 :  *     ns1 = length of is1 (21 is fine) (Input)
    1545                 :  *     is2 = Section 2 data (Output)
    1546                 :  *     ns2 = length of is2 () (Input)
    1547                 :  *     is3 = Section 3 data (Output)
    1548                 :  *     ns3 = length of is3 (96 or 1600) (Input)
    1549                 :  *     is4 = Section 4 data (Output)
    1550                 :  *     ns4 = length of is4 (60) (Input)
    1551                 :  *     is5 = Section 5 data (Output)
    1552                 :  *     ns5 = length of is5 (49 is fine) (Input)
    1553                 :  *     is6 = Section 6 data (Output)
    1554                 :  *     ns6 = length of is6 (6 is fine) (Input)
    1555                 :  *     is7 = Section 7 data (Output)
    1556                 :  *     ns7 = length of is7 (8 is fine) (Input)
    1557                 :  *      ib = Bitmap if user requested it, and it was packed (Output)
    1558                 :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Output)
    1559                 :  *   ipack = The message to unpack (This is assumed to be Big endian) (Input)
    1560                 :  *     nd5 = The size of ipack (Input)
    1561                 :  *  xmissp = The floating point representation for the primary missing value.
    1562                 :  *           (Input/Output)
    1563                 :  *  xmisss = The floating point representation for the secondary missing
    1564                 :  *           value (Input/Output)
    1565                 :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
    1566                 :  *  iclean = 1 means the user wants the unpacked data returned without
    1567                 :  *           missing values in it. 0 means embed the missing values. (Input)
    1568                 :  *  l3264b = Integer word length in bits (32 or 64) (Input)
    1569                 :  *  iendpk = A 1 means no more grids in this message, a 0 means more grids.
    1570                 :  *           (Output)
    1571                 :  * jer(ndjer,2) = error codes along with severity. (Output)
    1572                 :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
    1573                 :  *    kjer = number of error messages stored in jer. (Output)
    1574                 :  *
    1575                 :  * FILES/DATABASES: None
    1576                 :  *
    1577                 :  * RETURNS: void
    1578                 :  *
    1579                 :  * HISTORY
    1580                 :  *  12/2003 Arthur Taylor (MDL/RSIS): Created.
    1581                 :  *
    1582                 :  * NOTES
    1583                 :  * Inefficiencies: have to memswap ipack multiple times.
    1584                 :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
    1585                 :  * MDL attempts to always return grids in scan mode 0100????
    1586                 :  * ToDo: Check length of parameters better.
    1587                 :  *
    1588                 :  * According to MDL's unpk_grib2.f, it currently supports (so for others we
    1589                 :  * call the NCEP routines):
    1590                 :  *    TEMPLATE 3.0   EQUIDISTANT CYLINDRICAL LATITUDE/LONGITUDE
    1591                 :  *    TEMPLATE 3.10  MERCATOR
    1592                 :  *    TEMPLATE 3.20  POLAR STEREOGRAPHIC
    1593                 :  *    TEMPLATE 3.30  LAMBERT
    1594                 :  *    TEMPLATE 3.90  ORTHOGRAPHIC SPACE VIEW
    1595                 :  *    TEMPLATE 3.110 EQUATORIAL AZIMUTHAL EQUIDISTANT
    1596                 :  *    TEMPLATE 3.120 AZIMUTH-RANGE (RADAR)
    1597                 :  *
    1598                 :  *    TEMPLATE 4.0  ANALYSIS OR FORECAST AT A LEVEL AND POINT
    1599                 :  *    TEMPLATE 4.1  INDIVIDUAL ENSEMBLE
    1600                 :  *    TEMPLATE 4.2  DERIVED FORECAST BASED ON ENSEMBLES
    1601                 :  *    TEMPLATE 4.8  AVERAGE, ACCUMULATION, EXTREMES
    1602                 :  *    TEMPLATE 4.20 RADAR
    1603                 :  *    TEMPLATE 4.30 SATELLITE
    1604                 :  *
    1605                 :  *    TEMPLATE 5.0  SIMPLE PACKING
    1606                 :  *    TEMPLATE 5.2  COMPLEX PACKING
    1607                 :  *    TEMPLATE 5.3  COMPLEX PACKING AND SPATIAL DIFFERENCING
    1608                 :  *
    1609                 :  * Correction to "unpk_grib2.f" : It also supports:
    1610                 :  *    TEMPLATE 4.9  Probability forecast in a time interval
    1611                 :  *
    1612                 :  *****************************************************************************
    1613                 :  */
    1614               2 : void unpk_grib2 (sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nd2x3,
    1615                 :                  sInt4 * idat, sInt4 * nidat, float * rdat, sInt4 * nrdat,
    1616                 :                  sInt4 * is0, sInt4 * ns0, sInt4 * is1, sInt4 * ns1,
    1617                 :                  sInt4 * is2, sInt4 * ns2, sInt4 * is3, sInt4 * ns3,
    1618                 :                  sInt4 * is4, sInt4 * ns4, sInt4 * is5, sInt4 * ns5,
    1619                 :                  sInt4 * is6, sInt4 * ns6, sInt4 * is7, sInt4 * ns7,
    1620                 :                  sInt4 * ib, sInt4 * ibitmap, sInt4 * ipack, sInt4 * nd5,
    1621                 :                  float * xmissp, float * xmisss, sInt4 * inew,
    1622                 :                  sInt4 * iclean, sInt4 * l3264b, sInt4 * iendpk, sInt4 * jer,
    1623                 :                  sInt4 * ndjer, sInt4 * kjer)
    1624                 : {
    1625                 :    unsigned char *c_ipack; /* The compressed data as char instead of sInt4
    1626                 :                             * so it is easier to work with. */
    1627                 :    sInt4 gdsTmpl;
    1628                 :    sInt4 pdsTmpl;
    1629                 :    sInt4 drsTmpl;
    1630                 :    sInt4 numGrps;
    1631               2 :       char f_useMDL = 0;   /* Instructed 3/8/2005 10:30 to not use MDL. */
    1632                 :    uChar f_noBitmap;    /* 0 if bitmap, else no bitmap. */
    1633                 :    sInt4 orderDiff;
    1634                 : 
    1635               2 :    if (FindTemplateIDs (ipack, *nd5, 0, &gdsTmpl, &pdsTmpl, &drsTmpl,
    1636                 :                         &numGrps, &f_noBitmap, &orderDiff) != 0) {
    1637               0 :       jer[0 + *ndjer] = 2;
    1638               0 :       jer[0] = 3000;    /* Couldn't figure out which templates are used. */
    1639               0 :       *kjer = 1;
    1640                 :    }
    1641               2 :    if ((gdsTmpl != 0) && (gdsTmpl != 10) && (gdsTmpl != 20) &&
    1642               0 :        (gdsTmpl != 30) && (gdsTmpl != 90) && (gdsTmpl != 110) &&
    1643               0 :        (gdsTmpl != 120)) {
    1644               0 :       f_useMDL = 0;
    1645                 :    }
    1646               4 :    if ((pdsTmpl != 0) && (pdsTmpl != 1) && (pdsTmpl != 2) &&
    1647               2 :        (pdsTmpl != 8) && (pdsTmpl != 9) && (pdsTmpl != 20) &&
    1648               0 :        (pdsTmpl != 30)) {
    1649               0 :       f_useMDL = 0;
    1650                 :    }
    1651               2 :    if ((drsTmpl != 0) && (drsTmpl != 2) && (drsTmpl != 3)) {
    1652               0 :       f_useMDL = 0;
    1653                 :    }
    1654                 :    /* MDL GRIB2 lib does not support drsTmpl 2 or 3 if there is a bitmap. */
    1655               2 :    if ((!f_noBitmap) && ((drsTmpl == 2) || (drsTmpl == 3))) {
    1656               0 :       f_useMDL = 0;
    1657                 :    }
    1658                 :    /* MDL GRIB2 lib does not support anything but second order differencing. */
    1659               2 :    if ((drsTmpl == 3) && (orderDiff != 2) && (orderDiff != 0)) {
    1660               2 :       f_useMDL = 0;
    1661                 :    }
    1662                 : 
    1663                 : #ifdef _FORTRAN
    1664                 :    if (f_useMDL) {
    1665                 :       jmin = (sInt4 *) malloc (numGrps * sizeof (sInt4));
    1666                 :       lbit = (sInt4 *) malloc (numGrps * sizeof (sInt4));
    1667                 :       nov = (sInt4 *) malloc (numGrps * sizeof (sInt4));
    1668                 :       iwork = (sInt4 *) malloc ((*nd2x3) * sizeof (sInt4));
    1669                 : 
    1670                 :       UNPK_G2MDL (kfildo, jmin, lbit, nov, iwork, ain, iain, nd2x3, idat,
    1671                 :                   nidat, rdat, nrdat, is0, ns0, is1, ns1, is2, ns2, is3, ns3,
    1672                 :                   is4, ns4, is5, ns5, is6, ns6, is7, ns7, ib, ibitmap, ipack,
    1673                 :                   nd5, xmissp, xmisss, inew, iclean, l3264b, iendpk, jer,
    1674                 :                   ndjer, kjer);
    1675                 : /*
    1676                 :       if (1==1) {
    1677                 :          int i;
    1678                 :          for (i=0; i < *nd2x3; i++) {
    1679                 :             if (ain[i] != 9999) {
    1680                 :                fprintf (stderr, "here grib2api.c: ain[%d] %f\n", i, ain[i]);
    1681                 :             }
    1682                 :          }
    1683                 :       }
    1684                 : */
    1685                 :       free (jmin);
    1686                 :       free (lbit);
    1687                 :       free (nov);
    1688                 :       free (iwork);
    1689                 : 
    1690                 :       /* Check the behavior of the NCEP routines. */
    1691                 : /*
    1692                 : #ifdef DEBUG
    1693                 :       validate ("check2.txt", ain, iain, nd2x3, idat, nidat, rdat, nrdat,
    1694                 :                 is0, ns0, is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5,
    1695                 :                 is6, ns6, is7, ns7, ib, ibitmap, xmissp, xmisss, iendpk,
    1696                 :                 jer, ndjer, kjer);
    1697                 :       clear (ain, iain, nd2x3, idat, nidat, rdat, nrdat, is0, ns0, is1, ns1,
    1698                 :              is2, ns2, is3, ns3, is4, ns4, is5, ns5, is6, ns6, is7, ns7, ib,
    1699                 :              ibitmap, xmissp, xmisss, iendpk, jer, ndjer, kjer);
    1700                 : #ifdef LITTLE_ENDIAN
    1701                 :       memswp (ipack, sizeof (sInt4), *nd5);
    1702                 : #endif
    1703                 :       c_ipack = (unsigned char *) ipack;
    1704                 :       unpk_g2ncep (kfildo, ain, iain, nd2x3, idat, nidat, rdat, nrdat, is0,
    1705                 :                    ns0, is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5,
    1706                 :                    is6, ns6, is7, ns7, ib, ibitmap, c_ipack, nd5, xmissp,
    1707                 :                    xmisss, inew, iclean, l3264b, iendpk, jer, ndjer, kjer);
    1708                 : #ifdef LITTLE_ENDIAN
    1709                 :       memswp (ipack, sizeof (sInt4), *nd5);
    1710                 : #endif
    1711                 :       validate ("check1.txt", ain, iain, nd2x3, idat, nidat, rdat, nrdat,
    1712                 :                 is0, ns0, is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5,
    1713                 :                 is6, ns6, is7, ns7, ib, ibitmap, xmissp, xmisss, iendpk, jer,
    1714                 :                 ndjer, kjer);
    1715                 : #endif
    1716                 : */
    1717                 :    } else {
    1718                 : #endif
    1719                 :       /* Since NCEP's code works with byte level stuff, we need to un-do the
    1720                 :        * byte swap of the (int *) data, then cast it to an (unsigned char *) */
    1721                 : #ifdef LITTLE_ENDIAN
    1722                 :       /* Can't make this dependent on inew, since they could have a sequence
    1723                 :        * of get first message... do stuff, get second message, which
    1724                 :        * unfortunately means they would have to get the first message again,
    1725                 :        * causing 2 swaps, and breaking their second request for the first
    1726                 :        * message (as well as their second message). */
    1727               2 :       memswp (ipack, sizeof (sInt4), *nd5);
    1728                 : #endif
    1729               2 :       c_ipack = (unsigned char *) ipack;
    1730               2 :       unpk_g2ncep (kfildo, ain, iain, nd2x3, idat, nidat, rdat, nrdat, is0,
    1731                 :                    ns0, is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5,
    1732                 :                    is6, ns6, is7, ns7, ib, ibitmap, c_ipack, nd5, xmissp,
    1733                 :                    xmisss, inew, iclean, l3264b, iendpk, jer, ndjer, kjer);
    1734                 : 
    1735                 : #ifdef LITTLE_ENDIAN
    1736                 :       /* Swap back because we could be called again for the subgrid data. */
    1737               2 :       memswp (ipack, sizeof (sInt4), *nd5);
    1738                 : #endif
    1739                 : #ifdef _FORTRAN
    1740                 :    }
    1741                 : #endif
    1742               2 : }
    1743                 : 
    1744                 : /* Not sure I need this... It is intended to provide a way to call it from
    1745                 :  * FORTRAN, but I'm not sure it is needed. */
    1746                 : /* gcc has two __ if there is one _ in the procedure name. */
    1747               0 : void unpk_grib2__ (sInt4 * kfildo, float * ain, sInt4 * iain,
    1748                 :                    sInt4 * nd2x3, sInt4 * idat, sInt4 * nidat, float * rdat,
    1749                 :                    sInt4 * nrdat, sInt4 * is0, sInt4 * ns0, sInt4 * is1,
    1750                 :                    sInt4 * ns1, sInt4 * is2, sInt4 * ns2, sInt4 * is3,
    1751                 :                    sInt4 * ns3, sInt4 * is4, sInt4 * ns4, sInt4 * is5,
    1752                 :                    sInt4 * ns5, sInt4 * is6, sInt4 * ns6, sInt4 * is7,
    1753                 :                    sInt4 * ns7, sInt4 * ib, sInt4 * ibitmap, sInt4 * ipack,
    1754                 :                    sInt4 * nd5, float * xmissp, float * xmisss,
    1755                 :                    sInt4 * inew, sInt4 * iclean, sInt4 * l3264b,
    1756                 :                    sInt4 * iendpk, sInt4 * jer, sInt4 * ndjer, sInt4 * kjer)
    1757                 : {
    1758               0 :    unpk_grib2 (kfildo, ain, iain, nd2x3, idat, nidat, rdat, nrdat, is0, ns0,
    1759                 :                is1, ns1, is2, ns2, is3, ns3, is4, ns4, is5, ns5, is6, ns6,
    1760                 :                is7, ns7, ib, ibitmap, ipack, nd5, xmissp, xmisss, inew,
    1761                 :                iclean, l3264b, iendpk, jer, ndjer, kjer);
    1762               0 : }
    1763                 : 
    1764                 : /*****************************************************************************
    1765                 :  * C_pkGrib2() --
    1766                 :  *
    1767                 :  * Arthur Taylor / MDL
    1768                 :  *
    1769                 :  * PURPOSE
    1770                 :  *   This procedure is the main API for encoding GRIB2 messages.  It is
    1771                 :  * intended to call NCEP's GRIB2 library.
    1772                 :  *
    1773                 :  * ARGUMENTS
    1774                 :  *     ain = Contains the data to pack if the original data was float data.
    1775                 :  *           (size = nd2x3) (Input)
    1776                 :  *    iain = Contains the data to pack if the original data was integer data.
    1777                 :  *           (size = nd2x3) (Input)
    1778                 :  *      nx = The number of rows in the gridded product. (Input)
    1779                 :  *      ny = The number of columns in the gridded products. (Input)
    1780                 :  *    idat = local use data if it is integer (stored in section 2). (Input)
    1781                 :  *   nidat = length of idat. (Input)
    1782                 :  *    rdat = local use data if it is a float (Input)
    1783                 :  *   nrdat = length of rdat. (Input)
    1784                 :  *     is0 = Section 0 data (element 7 should be set by caller) (Input/Output)
    1785                 :  *     ns0 = length of is0 (16 is fine) (Input)
    1786                 :  *     is1 = Section 1 data (Input/Output)
    1787                 :  *     ns1 = length of is1 (21 is fine) (Input)
    1788                 :  *     is3 = Section 3 data (Input/Output)
    1789                 :  *     ns3 = length of is3 (96 or 1600) (Input)
    1790                 :  *     is4 = Section 4 data (Input/Output)
    1791                 :  *     ns4 = length of is4 (60) (Input)
    1792                 :  *     is5 = Section 5 data (Input/Output)
    1793                 :  *     ns5 = length of is5 (49 is fine) (Input)
    1794                 :  *     is6 = Section 6 data (Input/Output)
    1795                 :  *     ns6 = length of is6 (6 is fine) (Input)
    1796                 :  *     is7 = Section 7 data (Input/Output)
    1797                 :  *     ns7 = length of is7 (8 is fine) (Input)
    1798                 :  *      ib = Bitmap if user requested it, and it was packed (Input/Output)
    1799                 :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Input/Output)
    1800                 :  *   ipack = The message to unpack (This is assumed to be Big endian) (Output)
    1801                 :  *     nd5 = The size of ipack (250 + NX*NY + (NX*NY)/8 + num local data) (In)
    1802                 :  *   missp = The integer representation for the primary missing value. (Input)
    1803                 :  *  xmissp = The float representation for the primary missing value. (Input)
    1804                 :  *   misss = The integer representation for the secondary missing value. (In)
    1805                 :  *  xmisss = The float representation for the secondary missing value (Input)
    1806                 :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
    1807                 :  *   minpk = minimum size of groups in complex and second order differencing
    1808                 :  *           methods.  Recommended value 14 (Input)
    1809                 :  *  iclean = 1 means no primary missing values embedded in the data field,
    1810                 :  *           0 means there are primary missing values in the data (Input/Out)
    1811                 :  *  l3264b = Integer word length in bits (32 or 64) (Input)
    1812                 :  * jer(ndjer,2) = error codes along with severity. (Output)
    1813                 :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
    1814                 :  *    kjer = number of error messages stored in jer. (Output)
    1815                 :  *
    1816                 :  * FILES/DATABASES: None
    1817                 :  *
    1818                 :  * RETURNS: void
    1819                 :  *
    1820                 :  * HISTORY
    1821                 :  *   1/2004 Arthur Taylor (MDL/RSIS): Created.
    1822                 :  *
    1823                 :  * NOTES
    1824                 :  * Inefficiencies: have to memswap ipack multiple times.
    1825                 :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
    1826                 :  * MDL attempts to always return grids in scan mode 0100????
    1827                 :  * ToDo: Check length of parameters better.
    1828                 :  *
    1829                 :  * According to MDL's pk_grib2.f, it currently supports (so for others we
    1830                 :  * call the NCEP routines):
    1831                 :  *    TEMPLATE 3.0   EQUIDISTANT CYLINDRICAL LATITUDE/LONGITUDE
    1832                 :  *    TEMPLATE 3.10  MERCATOR
    1833                 :  *    TEMPLATE 3.20  POLAR STEREOGRAPHIC
    1834                 :  *    TEMPLATE 3.30  LAMBERT
    1835                 :  *    TEMPLATE 3.90  ORTHOGRAPHIC SPACE VIEW
    1836                 :  *    TEMPLATE 3.110 EQUATORIAL AZIMUTHAL EQUIDISTANT
    1837                 :  *    TEMPLATE 3.120 AZIMUTH-RANGE (RADAR)
    1838                 :  *
    1839                 :  *    TEMPLATE 4.0  ANALYSIS OR FORECAST AT A LEVEL AND POINT
    1840                 :  *    TEMPLATE 4.1  INDIVIDUAL ENSEMBLE
    1841                 :  *    TEMPLATE 4.2  DERIVED FORECAST BASED ON ENSEMBLES
    1842                 :  *    TEMPLATE 4.8  AVERAGE, ACCUMULATION, EXTREMES
    1843                 :  *    TEMPLATE 4.20 RADAR
    1844                 :  *    TEMPLATE 4.30 SATELLITE
    1845                 :  *
    1846                 :  *    TEMPLATE 5.0  SIMPLE PACKING
    1847                 :  *    TEMPLATE 5.2  COMPLEX PACKING
    1848                 :  *    TEMPLATE 5.3  COMPLEX PACKING AND SPATIAL DIFFERENCING
    1849                 :  *
    1850                 :  * Correction to "pk_grib2.f" : It also supports:
    1851                 :  *    TEMPLATE 4.9  Probability forecast in a time interval
    1852                 :  *
    1853                 :  *****************************************************************************
    1854                 :  */
    1855               0 : int C_pkGrib2 (unsigned char *cgrib, sInt4 *sec0, sInt4 *sec1,
    1856                 :                unsigned char *csec2, sInt4 lcsec2,
    1857                 :                sInt4 *igds, sInt4 *igdstmpl, sInt4 *ideflist,
    1858                 :                sInt4 idefnum, sInt4 ipdsnum, sInt4 *ipdstmpl,
    1859                 :                float *coordlist, sInt4 numcoord, sInt4 idrsnum,
    1860                 :                sInt4 *idrstmpl, float *fld, sInt4 ngrdpts,
    1861                 :                sInt4 ibmap, sInt4 *bmap)
    1862                 : {
    1863                 :    int ierr;      /* error value from grib2 library. */
    1864                 : 
    1865               0 :    if ((ierr = g2_create (cgrib, sec0, sec1)) == -1) {
    1866                 :       /* Tried to use for version other than GRIB Ed 2 */
    1867               0 :       return -1;
    1868                 :    }
    1869                 : 
    1870               0 :    if ((ierr = g2_addlocal (cgrib, csec2, lcsec2)) < 0) {
    1871                 :       /* Some how got a bad section 2.  Should be impossible unless an
    1872                 :        * assert was broken. */
    1873               0 :       return -2;
    1874                 :    }
    1875                 : 
    1876               0 :    if ((ierr = g2_addgrid (cgrib, igds, igdstmpl, ideflist, idefnum)) < 0) {
    1877                 :       /* Some how got a bad section 3.  Only way would be should be with an
    1878                 :        * unsupported template number unless an assert was broken. */
    1879               0 :       return -3;
    1880                 :    }
    1881                 : 
    1882               0 :    if ((ierr = g2_addfield (cgrib, ipdsnum, ipdstmpl, coordlist, numcoord,
    1883                 :                             idrsnum, idrstmpl, fld, ngrdpts, ibmap,
    1884                 :                             bmap)) < 0) {
    1885               0 :       return -4;
    1886                 :    }
    1887                 : 
    1888               0 :    if ((ierr = g2_gribend (cgrib)) < 0) {
    1889               0 :       return -5;
    1890                 :    }
    1891                 : 
    1892               0 :    return ierr;
    1893                 : }
    1894                 : 
    1895                 : /*****************************************************************************
    1896                 :  * pk_grib2() --
    1897                 :  *
    1898                 :  * Arthur Taylor / MDL
    1899                 :  *
    1900                 :  * PURPOSE
    1901                 :  *   This procedure is the main API for encoding GRIB2 messages.  It is
    1902                 :  * intended to be a branching routine to call either the MDL GRIB2 library,
    1903                 :  * or the NCEP GRIB2 library, depending on which template it sees in the
    1904                 :  * message.
    1905                 :  *  Currently it calls both for debug purposes.
    1906                 :  *
    1907                 :  * ARGUMENTS
    1908                 :  *  kfildo = Unit number for output diagnostics (C ignores this). (Input)
    1909                 :  *     ain = Contains the data to pack if the original data was float data.
    1910                 :  *           (size = nd2x3) (Input)
    1911                 :  *    iain = Contains the data to pack if the original data was integer data.
    1912                 :  *           (size = nd2x3) (Input)
    1913                 :  *      nx = The number of rows in the gridded product. (Input)
    1914                 :  *      ny = The number of columns in the gridded products. (Input)
    1915                 :  *    idat = local use data if it is integer (stored in section 2). (Input)
    1916                 :  *   nidat = length of idat. (Input)
    1917                 :  *    rdat = local use data if it is a float (Input)
    1918                 :  *   nrdat = length of rdat. (Input)
    1919                 :  *     is0 = Section 0 data (element 7 should be set by caller) (Input/Output)
    1920                 :  *     ns0 = length of is0 (16 is fine) (Input)
    1921                 :  *     is1 = Section 1 data (Input/Output)
    1922                 :  *     ns1 = length of is1 (21 is fine) (Input)
    1923                 :  *     is3 = Section 3 data (Input/Output)
    1924                 :  *     ns3 = length of is3 (96 or 1600) (Input)
    1925                 :  *     is4 = Section 4 data (Input/Output)
    1926                 :  *     ns4 = length of is4 (60) (Input)
    1927                 :  *     is5 = Section 5 data (Input/Output)
    1928                 :  *     ns5 = length of is5 (49 is fine) (Input)
    1929                 :  *     is6 = Section 6 data (Input/Output)
    1930                 :  *     ns6 = length of is6 (6 is fine) (Input)
    1931                 :  *     is7 = Section 7 data (Input/Output)
    1932                 :  *     ns7 = length of is7 (8 is fine) (Input)
    1933                 :  *      ib = Bitmap if user requested it, and it was packed (Input/Output)
    1934                 :  * ibitmap = 0 means ib is invalid, 1 means ib is valid. (Input/Output)
    1935                 :  *   ipack = The message to unpack (This is assumed to be Big endian) (Output)
    1936                 :  *     nd5 = The size of ipack (250 + NX*NY + (NX*NY)/8 + num local data) (In)
    1937                 :  *   missp = The integer representation for the primary missing value. (Input)
    1938                 :  *  xmissp = The float representation for the primary missing value. (Input)
    1939                 :  *   misss = The integer representation for the secondary missing value. (In)
    1940                 :  *  xmisss = The float representation for the secondary missing value (Input)
    1941                 :  *     new = 1 if this is the first grid to be unpacked, else 0. (Input)
    1942                 :  *   minpk = minimum size of groups in complex and second order differencing
    1943                 :  *           methods.  Recommended value 14 (Input)
    1944                 :  *  iclean = 1 means no primary missing values embedded in the data field,
    1945                 :  *           0 means there are primary missing values in the data (Input/Out)
    1946                 :  *  l3264b = Integer word length in bits (32 or 64) (Input)
    1947                 :  * jer(ndjer,2) = error codes along with severity. (Output)
    1948                 :  *   ndjer = 1/2 length of jer. (>= 15) (Input)
    1949                 :  *    kjer = number of error messages stored in jer. (Output)
    1950                 :  *
    1951                 :  * FILES/DATABASES: None
    1952                 :  *
    1953                 :  * RETURNS: void
    1954                 :  *
    1955                 :  * HISTORY
    1956                 :  *   1/2004 Arthur Taylor (MDL/RSIS): Created.
    1957                 :  *
    1958                 :  * NOTES
    1959                 :  * Inefficiencies: have to memswap ipack multiple times.
    1960                 :  * MDL handles is5[12], is5[23], and is5[27] in an "interesting" manner.
    1961                 :  * MDL attempts to always return grids in scan mode 0100????
    1962                 :  * ToDo: Check length of parameters better.
    1963                 :  *
    1964                 :  * According to MDL's pk_grib2.f, it currently supports (so for others we
    1965                 :  * call the NCEP routines):
    1966                 :  *    TEMPLATE 3.0   EQUIDISTANT CYLINDRICAL LATITUDE/LONGITUDE
    1967                 :  *    TEMPLATE 3.10  MERCATOR
    1968                 :  *    TEMPLATE 3.20  POLAR STEREOGRAPHIC
    1969                 :  *    TEMPLATE 3.30  LAMBERT
    1970                 :  *    TEMPLATE 3.90  ORTHOGRAPHIC SPACE VIEW
    1971                 :  *    TEMPLATE 3.110 EQUATORIAL AZIMUTHAL EQUIDISTANT
    1972                 :  *    TEMPLATE 3.120 AZIMUTH-RANGE (RADAR)
    1973                 :  *
    1974                 :  *    TEMPLATE 4.0  ANALYSIS OR FORECAST AT A LEVEL AND POINT
    1975                 :  *    TEMPLATE 4.1  INDIVIDUAL ENSEMBLE
    1976                 :  *    TEMPLATE 4.2  DERIVED FORECAST BASED ON ENSEMBLES
    1977                 :  *    TEMPLATE 4.8  AVERAGE, ACCUMULATION, EXTREMES
    1978                 :  *    TEMPLATE 4.20 RADAR
    1979                 :  *    TEMPLATE 4.30 SATELLITE
    1980                 :  *
    1981                 :  *    TEMPLATE 5.0  SIMPLE PACKING
    1982                 :  *    TEMPLATE 5.2  COMPLEX PACKING
    1983                 :  *    TEMPLATE 5.3  COMPLEX PACKING AND SPATIAL DIFFERENCING
    1984                 :  *
    1985                 :  * Correction to "pk_grib2.f" : It also supports:
    1986                 :  *    TEMPLATE 4.9  Probability forecast in a time interval
    1987                 :  *
    1988                 :  *****************************************************************************
    1989                 :  */
    1990               0 : void pk_grib2 (sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nx,
    1991                 :                sInt4 * ny, sInt4 * idat, sInt4 * nidat, float * rdat,
    1992                 :                sInt4 * nrdat, sInt4 * is0, sInt4 * ns0, sInt4 * is1,
    1993                 :                sInt4 * ns1, sInt4 * is3, sInt4 * ns3, sInt4 * is4,
    1994                 :                sInt4 * ns4, sInt4 * is5, sInt4 * ns5, sInt4 * is6,
    1995                 :                sInt4 * ns6, sInt4 * is7, sInt4 * ns7, sInt4 * ib,
    1996                 :                sInt4 * ibitmap, sInt4 * ipack, sInt4 * nd5, sInt4 * missp,
    1997                 :                float * xmissp, sInt4 * misss, float * xmisss, sInt4 * inew,
    1998                 :                sInt4 * minpk, sInt4 * iclean, sInt4 * l3264b, sInt4 * jer,
    1999                 :                sInt4 * ndjer, sInt4 * kjer)
    2000                 : {
    2001                 : #ifndef _FORTRAN
    2002                 :    
    2003               0 :    printf ("Can not pack things unless using FORTRAN!\n");
    2004                 :    return;
    2005                 : 
    2006                 : #else
    2007                 : 
    2008                 :    sInt4 gdsTmpl;
    2009                 :    sInt4 pdsTmpl;
    2010                 :    sInt4 drsTmpl;
    2011                 :    sInt4 *jmax;
    2012                 :    sInt4 *jmin;
    2013                 :    sInt4 *lbit;
    2014                 :    sInt4 *nov;
    2015                 :    sInt4 *misslx;
    2016                 :    sInt4 *newbox;
    2017                 :    sInt4 *newboxp;
    2018                 :    sInt4 *ia;
    2019                 : /*   float *a;*/
    2020                 :    char f_useMDL = 1;
    2021                 :    int i;
    2022                 : 
    2023                 :    myAssert (*ndjer >= 8);
    2024                 :    /* Init the error handling array. */
    2025                 :    memset ((void *) jer, 0, 2 * *ndjer * sizeof (sInt4));
    2026                 :    for (i = 0; i < 8; i++) {
    2027                 :       jer[i] = i * 100;
    2028                 :    }
    2029                 :    *kjer = 8;
    2030                 : 
    2031                 :    gdsTmpl = is3[13 - 1];
    2032                 :    pdsTmpl = is4[8 - 1];
    2033                 :    drsTmpl = is5[10 - 1];
    2034                 :    if ((gdsTmpl != 0) && (gdsTmpl != 10) && (gdsTmpl != 20) &&
    2035                 :        (gdsTmpl != 30) && (gdsTmpl != 90) && (gdsTmpl != 110) &&
    2036                 :        (gdsTmpl != 120)) {
    2037                 :       f_useMDL = 0;
    2038                 :    }
    2039                 :    if ((pdsTmpl != 0) && (pdsTmpl != 1) && (pdsTmpl != 2) &&
    2040                 :        (pdsTmpl != 8) && (pdsTmpl != 9) && (pdsTmpl != 20) &&
    2041                 :        (pdsTmpl != 30)) {
    2042                 :       f_useMDL = 0;
    2043                 :    }
    2044                 :    if ((drsTmpl != 0) && (drsTmpl != 2) && (drsTmpl != 3)) {
    2045                 :       f_useMDL = 0;
    2046                 :    }
    2047                 : /*
    2048                 :    printf ("Forcing it to not use MDL encoder. \n");
    2049                 :    f_useMDL = 0;
    2050                 : */
    2051                 :    if (f_useMDL) {
    2052                 :       /* pk_cmplx.f ==> jmax(M), jmin(M), nov(M), lbit(M) */
    2053                 :       jmax = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2054                 :       jmin = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2055                 :       nov = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2056                 :       lbit = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2057                 :       /* pk_grib2.f ==> a(NX,NY), ia(NX,NY) */
    2058                 : /*      a = (float *) malloc ((*nx) * (*ny) * sizeof (float));*/
    2059                 :       ia = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2060                 :       /* pack_gp.f ==> misslx(NDG = NXY = nx*ny) */
    2061                 :       misslx = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2062                 :       /* Able to use jmax(nxy) for iwork(nxy) in int_map.f, and pk_missp.f */
    2063                 :       /* Able to use jmax(nxy) for work(nxy) in flt_map.f */
    2064                 :       /* reduce.f ==> newbox(ndg=nxy), newboxp(ndg=nxy) */
    2065                 :       newbox = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2066                 :       newboxp = (sInt4 *) malloc ((*nx) * (*ny) * sizeof (sInt4));
    2067                 : 
    2068                 :       /* other known automatic arrays... itemp(nidat) pk_sect2.f */
    2069                 :       /* other known automatic arrays... rtemp(nrdat) pk_sect2.f */
    2070                 : 
    2071                 :       /* a and ia are equivalenced here. */
    2072                 : #ifdef _FORTRAN
    2073                 :       PK_G2MDL (kfildo, jmax, jmin, lbit, nov, misslx, (float *) ia, ia,
    2074                 :                 newbox, newboxp, ain, iain, nx, ny, idat, nidat, rdat, nrdat,
    2075                 :                 is0, ns0, is1, ns1, is3, ns3, is4, ns4, is5, ns5, is6, ns6,
    2076                 :                 is7, ns7, ib, ibitmap, ipack, nd5, missp, xmissp, misss,
    2077                 :                 xmisss, inew, minpk, iclean, l3264b, jer, ndjer, kjer);
    2078                 : #endif /* _FORTRAN */
    2079                 : 
    2080                 :       free (jmax);
    2081                 :       free (jmin);
    2082                 :       free (nov);
    2083                 :       free (lbit);
    2084                 :       free (misslx);
    2085                 : /*      free (a);*/
    2086                 :       free (ia);
    2087                 :       free (newbox);
    2088                 :       free (newboxp);
    2089                 :    } else {
    2090                 : 
    2091                 : 
    2092                 : #ifdef PKNCEP
    2093                 : #ifdef LITTLE_ENDIAN
    2094                 :       /* Can't make this dependent on inew, since they could have a sequence
    2095                 :        * of get first message... do stuff, get second message, which
    2096                 :        * unfortunately means they would have to get the first message again,
    2097                 :        * causing 2 swaps, and breaking their second request for the first
    2098                 :        * message (as well as their second message). */
    2099                 : /*
    2100                 :       memswp (ipack, sizeof (sInt4), *nd5);
    2101                 : */
    2102                 : #endif
    2103                 :       c_ipack = (unsigned char *) ipack;
    2104                 :       pk_g2ncep (kfildo, ain, iain, nx, ny, idat, nidat, rdat, nrdat, is0,
    2105                 :                  ns0, is1, ns1, is3, ns3, is4, ns4, is5, ns5, is6, ns6, is7,
    2106                 :                  ns7, ib, ibitmap, c_ipack, nd5, missp, xmissp, misss, xmisss,
    2107                 :                  inew, minpk, iclean, l3264b, jer, ndjer, kjer);
    2108                 : 
    2109                 : #ifdef LITTLE_ENDIAN
    2110                 :       /* Swap back because we could be called again for the subgrid data. */
    2111                 :       memswp (ipack, sizeof (sInt4), *nd5);
    2112                 : #endif
    2113                 : #else
    2114                 : 
    2115                 :       printf ("Unable to use MDL Pack library?\n");
    2116                 :       printf ("gdsTmpl : %d , pdsTmpl %d : drsTmpl %d\n", gdsTmpl,
    2117                 :               pdsTmpl, drsTmpl);
    2118                 :       jer[0 + *ndjer] = 31415926;
    2119                 :       *kjer = 1;
    2120                 : #endif
    2121                 :    }
    2122                 : 
    2123                 : #endif /* _FORTRAN */
    2124                 : }

Generated by: LCOV version 1.7