Exemplo n.º 1
0
static void show_stats(uv_handle_t *handle, int status) {
  int64_t diff;

#if PRINT_STATS
  LOGF("connections: %d, read: %.1f gbit/s, write: %.1f gbit/s\n",
       read_sockets,
       gbit(nrecv, STATS_INTERVAL),
       gbit(nsent, STATS_INTERVAL));
#endif

  /* Exit if the show is over */
  if (!--stats_left) {

    uv_update_time();
    diff = uv_now() - start_time;

    LOGF("pump_%d: %.1f gbit/s\n", read_sockets,
        gbit(nrecv_total, diff));

    exit(0);
  }

  /* Reset read and write counters */
  nrecv = 0;
  nsent = 0;
}
Exemplo n.º 2
0
static void show_stats(uv_timer_t* handle, int status) {
  int64_t diff;
  int i;

#if PRINT_STATS
  LOGF("connections: %d, write: %.1f gbit/s\n",
       write_sockets,
       gbit(nsent, STATS_INTERVAL));
#endif

  /* Exit if the show is over */
  if (!--stats_left) {

    uv_update_time();
    diff = uv_now() - start_time;

    LOGF("%s_pump%d_client: %.1f gbit/s\n", type == TCP ? "tcp" : "pipe", write_sockets,
        gbit(nsent_total, diff));

    for (i = 0; i < write_sockets; i++) {
      uv_close(type == TCP ? (uv_handle_t*)&tcp_write_handles[i] : (uv_handle_t*)&pipe_write_handles[i], NULL);
    }

    exit(0);
  }

  /* Reset read and write counters */
  nrecv = 0;
  nsent = 0;
}
Exemplo n.º 3
0
static void read_show_stats() {
  int64_t diff;

  uv_update_time();
  diff = uv_now() - start_time;

  LOGF("%s_pump%d_server: %.1f gbit/s\n", type == TCP ? "tcp" : "pipe", max_read_sockets,
      gbit(nrecv_total, diff));
}
Exemplo n.º 4
0
/**
 * Returns the next bytes of a byte-buffer as an integer. Advances the
 * byte-buffer's cursor by the given number of bytes.
 *
 * @param[in]  bb       Pointer to a byte-buffer.
 * @param[in]  nbytes   The length of the integer in bytes.
 * @param[out] value    Pointer to an integer to hold the value.
 * @return     0        Success. \c *value will be set.
 * @retval    -1        The integer extends beyond the data in the byte-buffer.
 *                      \c *value will be unset.
 */
int bb_getInt(
    ByteBuf* const bb,
    const int     nbytes,
    g2int* const  value)
{
    if (bb->cursor + nbytes > bb->byteCount)
        return -1;

    /*
     * The casts in the following are known to be safe.
     */
    gbit((unsigned char*)bb->buf, value, (g2int)bb->cursor*CHAR_BIT,
            (g2int)nbytes*CHAR_BIT);

    bb->cursor += nbytes;

    return 0;
}
Exemplo n.º 5
0
g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char **csec2)
////$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack2
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 2 (Local Use Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
//
// USAGE:    int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,
//                          unsigned char **csec2)
//   INPUT ARGUMENT LIST:
//     cgrib    - char array containing Section 2 of the GRIB2 message
//     iofst    - Bit offset for the beginning of Section 2 in cgrib.
//
//   OUTPUT ARGUMENT LIST:
//     iofst    - Bit offset at the end of Section 2, returned.
//     lencsec2 - Length (in octets) of Local Use data
//     csec2    - Pointer to a char array containing local use data
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Array passed is not section 2
//                6 = memory allocation error
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$//
{

      g2int ierr,isecnum;
      g2int lensec,ipos,j;

      ierr=0;
      *lencsec2=0;
      *csec2=0;    // NULL

      gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
      *iofst=*iofst+32;
      *lencsec2=lensec-5;
      gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
      *iofst=*iofst+8;
      ipos=(*iofst/8);

      if ( isecnum != 2 ) {
         ierr=2;
         *lencsec2=0;
         fprintf(stderr,"g2_unpack2: Not Section 2 data.\n");
         return(ierr);
      }

      *csec2=(unsigned char *)malloc(*lencsec2);
      if (*csec2 == 0) {
         ierr=6;
         *lencsec2=0;
         return(ierr);
      }

      //printf(" SAGIPO %d \n",(int)ipos);
      for (j=0;j<*lencsec2;j++) {
         *(*csec2+j)=cgrib[ipos+j];
      }
      *iofst=*iofst+(*lencsec2*8);

      return(ierr);    // End of Section 2 processing

}
Exemplo n.º 6
0
g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
            g2int *numfields,g2int *numlocal)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_info 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
//
// ABSTRACT: This subroutine searches through a GRIB2 message and
//   returns the number of gridded fields found in the message and
//   the number (and maximum size) of Local Use Sections.
//   Also various checks  are performed
//   to see if the message is a valid GRIB2 message.
//
// PROGRAM HISTORY LOG:
// 2002-10-28  Gilbert
//
// USAGE:   int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
//            g2int *numfields,g2int *numlocal)
//   INPUT ARGUMENT:
//     cgrib    - Character pointer to the GRIB2 message
//
//   OUTPUT ARGUMENTS:      
//     listsec0 - pointer to an array containing information decoded from 
//                GRIB Indicator Section 0.
//                Must be allocated with >= 3 elements.
//                listsec0[0]=Discipline-GRIB Master Table Number
//                            (see Code Table 0.0)
//                listsec0[1]=GRIB Edition Number (currently 2)
//                listsec0[2]=Length of GRIB message
//     listsec1 - pointer to an array containing information read from GRIB 
//                Identification Section 1.
//                Must be allocated with >= 13 elements.
//                listsec1[0]=Id of originating centre (Common Code Table C-1)
//                listsec1[1]=Id of originating sub-centre (local table)
//                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
//                listsec1[3]=GRIB Local Tables Version Number 
//                listsec1[4]=Significance of Reference Time (Code Table 1.1)
//                listsec1[5]=Reference Time - Year (4 digits)
//                listsec1[6]=Reference Time - Month
//                listsec1[7]=Reference Time - Day
//                listsec1[8]=Reference Time - Hour
//                listsec1[9]=Reference Time - Minute
//                listsec1[10]=Reference Time - Second
//                listsec1[11]=Production status of data (Code Table 1.2)
//                listsec1[12]=Type of processed data (Code Table 1.3)
//     numfields- The number of gridded fields found in the GRIB message.
//                That is, the number of occurrences of Sections 4 - 7.
//     numlocal - The number of Local Use Sections ( Section 2 ) found in 
//                the GRIB message.
//
//     RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                1 = Beginning characters "GRIB" not found.
//                2 = GRIB message is not Edition 2.
//                3 = Could not find Section 1, where expected.
//                4 = End string "7777" found, but not where expected.
//                5 = End string "7777" not found at end of message.
//                6 = Invalid section number found.
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$
{
 
      g2int mapsec1len=13;
      g2int mapsec1[13]={2,2,1,1,1,2,1,1,1,1,1,1,1};
      g2int  i,j,istart,iofst,lengrib,lensec0,lensec1;
      g2int ipos,isecnum,nbits,lensec;

      *numlocal=0;
      *numfields=0;
//
//  Check for beginning of GRIB message in the first 100 bytes
//
      istart=-1;
      for (j=0;j<100;j++) {
        if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' &&
            cgrib[j+3]=='B') {
          istart=j;
          break;
        }
      }
      if (istart == -1) {
        printf("g2_info:  Beginning characters GRIB not found.");
        return(1);
      }
//
//  Unpack Section 0 - Indicator Section 
//
      iofst=8*(istart+6);
      gbit(cgrib,listsec0+0,iofst,8);     // Discipline
      iofst=iofst+8;
      gbit(cgrib,listsec0+1,iofst,8);     // GRIB edition number
      iofst=iofst+8;
      iofst=iofst+32;
      gbit(cgrib,&lengrib,iofst,32);        // Length of GRIB message
      iofst=iofst+32;
      listsec0[2]=lengrib;
      lensec0=16;
      ipos=istart+lensec0;
//
//  Currently handles only GRIB Edition 2.
//  
      if (listsec0[1] != 2) {
        printf("g2_info: can only decode GRIB edition 2.");
        return(2);
      }
//
//  Unpack Section 1 - Identification Section
//
      gbit(cgrib,&lensec1,iofst,32);        // Length of Section 1
      iofst=iofst+32;
      gbit(cgrib,&isecnum,iofst,8);         // Section number ( 1 )
      iofst=iofst+8;
      if (isecnum != 1) {
        printf("g2_info: Could not find section 1.");
        return(3);
      }
      //
      //   Unpack each input value in array listsec1 into the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapsec1.
      //
      for (i=0;i<mapsec1len;i++) {
        nbits=mapsec1[i]*8;
        gbit(cgrib,listsec1+i,iofst,nbits);
        iofst=iofst+nbits;
      }
      ipos=ipos+lensec1;
//
//  Loop through the remaining sections to see if they are valid.
//  Also count the number of times Section 2
//  and Section 4 appear.
//
      for (;;) {
        if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' &&
            cgrib[ipos+3]=='7') {
          ipos=ipos+4;
          if (ipos != (istart+lengrib)) {
            printf("g2_info: '7777' found, but not where expected.\n");
            return(4);
          }
          break;
        }
        
        iofst=ipos*8;
        gbit(cgrib,&lensec,iofst,32);        // Get Length of Section
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);         // Get Section number
        /*iofst=iofst+8;*/
        ipos=ipos+lensec;                 // Update beginning of section pointer
        if (ipos > (istart+lengrib)) {
          printf("g2_info: '7777'  not found at end of GRIB message.\n");
          return(5);
        }
        if ( isecnum>=2 && isecnum<=7 ) {
           if (isecnum == 2)      // Local Section 2
              //   increment counter for total number of local sections found
              (*numlocal)++;
            
           else if (isecnum == 4)
              //   increment counter for total number of fields found
              (*numfields)++;
        }
        else {
           printf("g2_info: Invalid section number found in GRIB message: %d\n"                   ,isecnum);
           return(6);
        }
        
      }

      return(0);

}
Exemplo n.º 7
0
int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float *fld)
/*//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    comunpack
//   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-10-29
//
// ABSTRACT: This subroutine unpacks a data field that was packed using a
//   complex packing algorithm as defined in the GRIB2 documention,
//   using info from the GRIB2 Data Representation Template 5.2 or 5.3.
//   Supports GRIB2 complex packing templates with or without
//   spatial differences (i.e. DRTs 5.2 and 5.3).
//
// PROGRAM HISTORY LOG:
// 2002-10-29  Gilbert
// 2004-12-16  Gilbert  -  Added test ( provided by Arthur Taylor/MDL )
//                         to verify that group widths and lengths are
//                         consistent with section length.
//
// USAGE:    int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,
//                         g2int *idrstmpl, g2int ndpts,g2float *fld)
//   INPUT ARGUMENT LIST:
//     cpack    - pointer to the packed data field.
//     lensec   - length of section 7 (used for error checking).
//     idrsnum  - Data Representation Template number 5.N
//                Must equal 2 or 3.
//     idrstmpl - pointer to the array of values for Data Representation
//                Template 5.2 or 5.3
//     ndpts    - The number of data values to unpack
//
//   OUTPUT ARGUMENT LIST:
//     fld      - Contains the unpacked data values.  fld must be allocated
//                with at least ndpts*sizeof(g2float) bytes before
//                calling this routine.
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE: 
//
//$$$*/
{

      g2int   nbitsd=0,isign;
      g2int  j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0;
      g2int  *ifld,*ifldmiss=0;
      g2int  *gref,*gwidth,*glen;
      g2int  itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen;
      g2int  msng1,msng2;
      g2float ref,bscale,dscale,rmiss1,rmiss2;
      g2int totBit, totLen;

      /*printf('IDRSTMPL: ',(idrstmpl(j),j=1,16)*/
      g2_rdieee(idrstmpl+0,&ref,1);
/*      printf("SAGTref: %f\n",ref);*/
      bscale = (g2float)int_power(2.0,idrstmpl[1]);
      dscale = (g2float)int_power(10.0,-idrstmpl[2]);
      nbitsgref = idrstmpl[3];
      itype = idrstmpl[4];
      ngroups = idrstmpl[9];
      nbitsgwidth = idrstmpl[11];
      nbitsglen = idrstmpl[15];
      if (idrsnum == 3)
         nbitsd=idrstmpl[17]*8;

      /*   Constant field*/

      if (ngroups == 0) {
         for (j=0;j<ndpts;j++) fld[j]=ref;
         return(0);
      }

      iofst=0;
      ifld=(g2int *)calloc(ndpts,sizeof(g2int));
      /*printf("ALLOC ifld: %d %x\n",(int)ndpts,ifld);*/
      gref=(g2int *)calloc(ngroups,sizeof(g2int));
      /*printf("ALLOC gref: %d %x\n",(int)ngroups,gref);*/
      gwidth=(g2int *)calloc(ngroups,sizeof(g2int));
      /*printf("ALLOC gwidth: %d %x\n",(int)ngroups,gwidth);*/
/*
//  Get missing values, if supplied
*/
      if ( idrstmpl[6] == 1 ) {
         if (itype == 0) 
            g2_rdieee(idrstmpl+7,&rmiss1,1);
         else 
            rmiss1=(g2float)idrstmpl[7];
      }
      if ( idrstmpl[6] == 2 ) {
         if (itype == 0) {
            g2_rdieee(idrstmpl+7,&rmiss1,1);
            g2_rdieee(idrstmpl+8,&rmiss2,1);
         }
         else {
            rmiss1=(g2float)idrstmpl[7];
            rmiss2=(g2float)idrstmpl[8];
         }
      }
      
      /*printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref);*/
/* 
//  Extract Spatial differencing values, if using DRS Template 5.3
*/
      if (idrsnum == 3) {
         if (nbitsd != 0) {
              gbit(cpack,&isign,iofst,1);
              iofst=iofst+1;
              gbit(cpack,&ival1,iofst,nbitsd-1);
              iofst=iofst+nbitsd-1;
              if (isign == 1) ival1=-ival1;
              if (idrstmpl[16] == 2) {
                 gbit(cpack,&isign,iofst,1);
                 iofst=iofst+1;
                 gbit(cpack,&ival2,iofst,nbitsd-1);
                 iofst=iofst+nbitsd-1;
                 if (isign == 1) ival2=-ival2;
              }
              gbit(cpack,&isign,iofst,1);
              iofst=iofst+1;
              gbit(cpack,&minsd,iofst,nbitsd-1);
              iofst=iofst+nbitsd-1;
              if (isign == 1) minsd=-minsd;
         }
         else {
              ival1=0;
              ival2=0;
              minsd=0;
         }
       /*printf("SDu %ld %ld %ld %ld \n",ival1,ival2,minsd,nbitsd);*/
      }
/*
//  Extract Each Group's reference value
*/
      /*printf("SAG1: %ld %ld %ld \n",nbitsgref,ngroups,iofst);*/
      if (nbitsgref != 0) {
         gbits(cpack,gref+0,iofst,nbitsgref,0,ngroups);
         itemp=nbitsgref*ngroups;
         iofst=iofst+itemp;
         if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
      }
      else {
         for (j=0;j<ngroups;j++)
              gref[j]=0;
      }
/*
//  Extract Each Group's bit width
*/
      /*printf("SAG2: %ld %ld %ld %ld \n",nbitsgwidth,ngroups,iofst,idrstmpl[10]);*/
      if (nbitsgwidth != 0) {
         gbits(cpack,gwidth+0,iofst,nbitsgwidth,0,ngroups);
         itemp=nbitsgwidth*ngroups;
         iofst=iofst+itemp;
         if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
      }
      else {
         for (j=0;j<ngroups;j++)
                gwidth[j]=0;
      }

      for (j=0;j<ngroups;j++)
          gwidth[j]=gwidth[j]+idrstmpl[10];
      
/*
//  Extract Each Group's length (number of values in each group)
*/
      glen=(g2int *)calloc(ngroups,sizeof(g2int));
      /*printf("ALLOC glen: %d %x\n",(int)ngroups,glen);*/
      /*printf("SAG3: %ld %ld %ld %ld %ld \n",nbitsglen,ngroups,iofst,idrstmpl[13],idrstmpl[12]);*/
      if (nbitsglen != 0) {
         gbits(cpack,glen,iofst,nbitsglen,0,ngroups);
         itemp=nbitsglen*ngroups;
         iofst=iofst+itemp;
         if (itemp%8 != 0) iofst=iofst+(8-(itemp%8));
      }
      else {
         for (j=0;j<ngroups;j++)
              glen[j]=0;
      }
      for (j=0;j<ngroups;j++) 
           glen[j]=(glen[j]*idrstmpl[13])+idrstmpl[12];
      glen[ngroups-1]=idrstmpl[14];
/*
//  Test to see if the group widths and lengths are consistent with number of
//  values, and length of section 7.
*/
      totBit = 0;
      totLen = 0;
      for (j=0;j<ngroups;j++) {
        totBit += (gwidth[j]*glen[j]);
        totLen += glen[j];
      }
      if (totLen != ndpts) {
        return 1;
      }
      if (totBit / 8. > lensec) {
        return 1;
      }
/*
//  For each group, unpack data values
*/
      if ( idrstmpl[6] == 0 ) {        /* no missing values*/
         n=0;
         for (j=0;j<ngroups;j++) {
           if (gwidth[j] != 0) {
             gbits(cpack,ifld+n,iofst,gwidth[j],0,glen[j]);
             for (k=0;k<glen[j];k++) {
               ifld[n]=ifld[n]+gref[j];
               n=n+1;
             }
           }
           else {
             for (l=n;l<n+glen[j];l++) ifld[l]=gref[j];
             n=n+glen[j];
           }
           iofst=iofst+(gwidth[j]*glen[j]);
         }
      }
      else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) {
         /* missing values included*/
         ifldmiss=(g2int *)malloc(ndpts*sizeof(g2int));
         /*printf("ALLOC ifldmiss: %d %x\n",(int)ndpts,ifldmiss);*/
         /*for (j=0;j<ndpts;j++) ifldmiss[j]=0;*/
         n=0;
         non=0;
         for (j=0;j<ngroups;j++) {
           /*printf(" SAGNGP %d %d %d %d\n",j,gwidth[j],glen[j],gref[j]);*/
           if (gwidth[j] != 0) {
             msng1=(g2int)int_power(2.0,gwidth[j])-1;
             msng2=msng1-1;
             gbits(cpack,ifld+n,iofst,gwidth[j],0,glen[j]);
             iofst=iofst+(gwidth[j]*glen[j]);
             for (k=0;k<glen[j];k++) {
               if (ifld[n] == msng1) {
                  ifldmiss[n]=1;
                  /*ifld[n]=0;*/
               }
               else if (idrstmpl[6]==2 && ifld[n]==msng2) {
                  ifldmiss[n]=2;
                  /*ifld[n]=0;*/
               }
               else {
                  ifldmiss[n]=0;
                  ifld[non++]=ifld[n]+gref[j];
               }
               n++;
             }
           }
           else {
             msng1=(g2int)int_power(2.0,nbitsgref)-1;
             msng2=msng1-1;
             if (gref[j] == msng1) {
                for (l=n;l<n+glen[j];l++) ifldmiss[l]=1;
             }
             else if (idrstmpl[6]==2 && gref[j]==msng2) {
                for (l=n;l<n+glen[j];l++) ifldmiss[l]=2;
             }
             else {
                for (l=n;l<n+glen[j];l++) ifldmiss[l]=0;
                for (l=non;l<non+glen[j];l++) ifld[l]=gref[j];
                non += glen[j];
             }
             n=n+glen[j];
           }
         }
      }

      if ( gref != 0 ) free(gref);
      if ( gwidth != 0 ) free(gwidth);
      if ( glen != 0 ) free(glen);
/*
//  If using spatial differences, add overall min value, and
//  sum up recursively
*/
      /*printf("SAGod: %ld %ld\n",idrsnum,idrstmpl[16]);*/
      if (idrsnum == 3) {         /* spatial differencing*/
         if (idrstmpl[16] == 1) {      /* first order*/
            ifld[0]=ival1;
            if ( idrstmpl[6] == 0 ) itemp=ndpts;        /* no missing values*/
            else  itemp=non;
            for (n=1;n<itemp;n++) {
               ifld[n]=ifld[n]+minsd;
               ifld[n]=ifld[n]+ifld[n-1];
            }
         }
         else if (idrstmpl[16] == 2) {    /* second order*/
            ifld[0]=ival1;
            ifld[1]=ival2;
            if ( idrstmpl[6] == 0 ) itemp=ndpts;        /* no missing values*/
            else  itemp=non;
            for (n=2;n<itemp;n++) {
               ifld[n]=ifld[n]+minsd;
               ifld[n]=ifld[n]+(2*ifld[n-1])-ifld[n-2];
            }
         }
      }
/*
//  Scale data back to original form
*/
      /*printf("SAGT: %f %f %f\n",ref,bscale,dscale);*/
      if ( idrstmpl[6] == 0 ) {        /* no missing values*/
         for (n=0;n<ndpts;n++) {
            fld[n]=(((g2float)ifld[n]*bscale)+ref)*dscale;
         }
      }
      else if ( idrstmpl[6]==1 || idrstmpl[6]==2 ) {
         /* missing values included*/
         non=0;
         for (n=0;n<ndpts;n++) {
            if ( ifldmiss[n] == 0 ) {
               fld[n]=(((g2float)ifld[non++]*bscale)+ref)*dscale;
               /*printf(" SAG %d %f %d %f %f %f\n",n,fld[n],ifld[non-1],bscale,ref,dscale);*/
            }
            else if ( ifldmiss[n] == 1 ) 
               fld[n]=rmiss1;
            else if ( ifldmiss[n] == 2 ) 
               fld[n]=rmiss2;
         }
         if ( ifldmiss != 0 ) free(ifldmiss);
      }

      if ( ifld != 0 ) free(ifld);

      return(0);
      
}
Exemplo n.º 8
0
g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl,
               g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float **fld)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack7 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 7 (Data Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
// 2002-12-20  Gilbert - Added GDT info to arguments
//                       and added 5.51 processing.
// 2003-08-29  Gilbert  - Added support for new templates using
//                        PNG and JPEG2000 algorithms/templates.
// 2004-11-29  Gilbert  - JPEG2000 now allowed to use WMO Template no. 5.40
//                        PNG now allowed to use WMO Template no. 5.41
// 2004-12-16  Taylor   - Added check on comunpack return code.
// 2008-12-23  Wesley   - Initialize Number of data points unpacked
//
// USAGE:    int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,
//                          g2int *igdstmpl, g2int idrsnum,
//                          g2int *idrstmpl, g2int ndpts,g2float **fld)
//   INPUT ARGUMENTS:
//     cgrib    - char array containing Section 7 of the GRIB2 message
//     iofst    - Bit offset of the beginning of Section 7 in cgrib.
//     igdsnum  - Grid Definition Template Number ( see Code Table 3.0)
//                ( Only used for DRS Template 5.51 )
//     igdstmpl - Pointer to an integer array containing the data values for
//                the specified Grid Definition
//                Template ( N=igdsnum ).  Each element of this integer
//                array contains an entry (in the order specified) of Grid
//                Definition Template 3.N
//                ( Only used for DRS Template 5.51 )
//     idrsnum  - Data Representation Template Number ( see Code Table 5.0)
//     idrstmpl - Pointer to an integer array containing the data values for
//                the specified Data Representation
//                Template ( N=idrsnum ).  Each element of this integer
//                array contains an entry (in the order specified) of Data
//                Representation Template 5.N
//     ndpts    - Number of data points unpacked and returned.
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset at the end of Section 7, returned.
//     fld      - Pointer to a float array containing the unpacked data field.
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Not section 7
//                4 = Unrecognized Data Representation Template
//                5 = need one of GDT 3.50 through 3.53 to decode DRT 5.51
//                6 = memory allocation error
//                7 = corrupt section 7.
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$//
{
      g2int ierr,isecnum;
      g2int ipos,lensec;
      g2float *lfld;

      ierr=0;
      *fld=0;     //NULL

      gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
      *iofst=*iofst+32;    
      gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
      *iofst=*iofst+8;

      if ( isecnum != 7 ) {
         ierr=2;
         //fprintf(stderr,"g2_unpack7: Not Section 7 data.\n");
         return(ierr);
      }

      ipos=(*iofst/8);
      lfld=(g2float *)calloc(ndpts ? ndpts : 1,sizeof(g2float));
      if (lfld == 0) {
         ierr=6;
         return(ierr);
      }
      *fld=lfld;

      if (idrsnum == 0) 
        simunpack(cgrib+ipos,idrstmpl,ndpts,lfld);
      else if (idrsnum == 2 || idrsnum == 3) {
        if (comunpack(cgrib+ipos,lensec,idrsnum,idrstmpl,ndpts,lfld) != 0) {
          return 7;
        }
      }
      else if( idrsnum == 4 ) {
        // Grid point data - IEEE Floating Point Data
        static const int one = 1;
        int is_lsb = *((char*)&one) == 1;
        if (idrstmpl[0] == 1) {
          // IEEE754 single precision
          memcpy(lfld, cgrib+ipos, 4 * ndpts );
          if( is_lsb ) {
              int i;
              unsigned char* ch_fld = (unsigned char*) lfld;
              for(i=0;i<ndpts;i++)
              {
                  unsigned char temp = ch_fld[i*4];
                  ch_fld[i*4] = ch_fld[i*4+3];
                  ch_fld[i*4+3] = temp;
                  temp = ch_fld[i*4+1];
                  ch_fld[i*4+1] = ch_fld[i*4+2];
                  ch_fld[i*4+2] = temp;
              }
          }
        }
        else if( idrstmpl[0] == 2) {
          // IEEE754 double precision
          // FIXME? due to the interface: we downgrade it to float
          int i;
          unsigned char* src = cgrib+ipos;
          if( is_lsb ) {
              for(i=0;i<ndpts;i++) {
                  unsigned char temp[8];
                  double d;
                  {
                    int j;
                    for(j = 0; j < 8; j++ )
                      temp[j] = src[i * 8 + 7 - j];
                  }
                  memcpy(&d, temp, 8);
                  lfld[i] = DoubleToFloatClamp(d);
              }
          }
          else {
              for(i=0;i<ndpts;i++) {
                  double d;
                  memcpy(&d, src + i * 8, 8);
                  lfld[i] = DoubleToFloatClamp(d);
              }
          }
        }
        else {
            fprintf(stderr,"g2_unpack7: Invalid precision=%ld for Data Section 5.4.\n", idrstmpl[0]);
            ierr=5;
            free(lfld);
            *fld=0;     //NULL
            return(ierr);
        }
      }
      else if (idrsnum == 50) {            // Spectral Simple
        simunpack(cgrib+ipos,idrstmpl,ndpts-1,lfld+1);
        rdieee(idrstmpl+4,lfld+0,1);
      }
      else if (idrsnum == 51)              //  Spectral complex
        if ( igdsnum>=50 && igdsnum <=53 ) 
          specunpack(cgrib+ipos,idrstmpl,ndpts,igdstmpl[0],igdstmpl[2],igdstmpl[2],lfld);
        else {
          fprintf(stderr,"g2_unpack7: Cannot use GDT 3.%d to unpack Data Section 5.51.\n",(int)igdsnum);
          ierr=5;
          free(lfld);
          *fld=0;     //NULL
          return(ierr);
        }
#ifdef USE_JPEG2000
      else if (idrsnum == 40 || idrsnum == 40000) {
        jpcunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld);
        }
#endif  /* USE_JPEG2000 */
#ifdef USE_PNG
      else if (idrsnum == 41 || idrsnum == 40010) {
        pngunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld);
        }
#endif  /* USE_PNG */
      else {
        fprintf(stderr,"g2_unpack7: Data Representation Template 5.%d not yet implemented.\n",(int)idrsnum);
        ierr=4;
        free(lfld);
        *fld=0;     //NULL
        return(ierr);
      }

      *iofst=*iofst+(8*lensec);
      
      return(ierr);    // End of Section 7 processing

}
Exemplo n.º 9
0
void seekgb(FILE *lugb,g2int iseek,g2int mseek,g2int *lskip,g2int *lgrib)
/*$$$  SUBPROGRAM DOCUMENTATION BLOCK
//
// SUBPROGRAM: seekgb         Searches a file for the next GRIB message.
//   PRGMMR: Gilbert          ORG: W/NP11      DATE: 2002-10-28
//
// ABSTRACT: This subprogram searches a file for the next GRIB Message.
//   The search is done starting at byte offset iseek of the file referenced 
//   by lugb for mseek bytes at a time.
//   If found, the starting position and length of the message are returned
//   in lskip and lgrib, respectively.
//   The search is terminated when an EOF or I/O error is encountered.
//
// PROGRAM HISTORY LOG:
// 2002-10-28  GILBERT   Modified from Iredell's skgb subroutine
// 2009-01-16  VUONG     Changed  lskip to 4 instead of sizof(g2int)
//
// USAGE:    seekgb(FILE *lugb,g2int iseek,g2int mseek,int *lskip,int *lgrib)
//   INPUT ARGUMENTS:
//     lugb       - FILE pointer for the file to search.  File must be
//                  opened before this routine is called.
//     iseek      - number of bytes in the file to skip before search
//     mseek      - number of bytes to search at a time
//   OUTPUT ARGUMENTS:
//     lskip      - number of bytes to skip from the beggining of the file
//                  to where the GRIB message starts
//     lgrib      - number of bytes in message (set to 0, if no message found)
//
// ATTRIBUTES:
//   LANGUAGE: C
//
//$$$*/
{
      g2int  ret;
      g2int k,k4,ipos,nread,lim,start,vers,lengrib;
      int    end;
      unsigned char *cbuf;

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
      *lgrib=0;
      cbuf=(unsigned char *)malloc(mseek);
      nread=mseek;
      ipos=iseek;

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*  LOOP UNTIL GRIB MESSAGE IS FOUND*/

      while (*lgrib==0 && nread==mseek) {

/*  READ PARTIAL SECTION*/

        ret=fseek(lugb,ipos,SEEK_SET);
        nread=fread(cbuf,sizeof(unsigned char),mseek,lugb);
        lim=nread-8;

/*  LOOK FOR 'GRIB...' IN PARTIAL SECTION*/

        for (k=0;k<lim;k++) {
          gbit(cbuf,&start,(k+0)*8,4*8);
          gbit(cbuf,&vers,(k+7)*8,1*8);
          if (start==1196575042 && (vers==1 || vers==2)) {
/*  LOOK FOR '7777' AT END OF GRIB MESSAGE*/
            if (vers == 1) gbit(cbuf,&lengrib,(k+4)*8,3*8);
            if (vers == 2) gbit(cbuf,&lengrib,(k+12)*8,4*8);
            ret=fseek(lugb,ipos+k+lengrib-4,SEEK_SET);
/*          Hard code to 4 instead of sizeof(g2int)*/
            k4=fread(&end,4,1,lugb);
            if (k4 == 1 && end == 926365495) {      /*GRIB message found*/
                *lskip=ipos+k;
                *lgrib=lengrib;
                break;
            }
          }
        }
        ipos=ipos+lim;
      }

      free(cbuf);
}
Exemplo n.º 10
0
g2int g2_unpack2(unsigned char *cgrib, size_t sz, g2int *iofst,g2int *lencsec2,
        unsigned char **csec2)
/*//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack2 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 2 (Local Use Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
// 2008-12-23  Wesley   - Initialize lencsec2 Length of Local Use data
// 2014-02-25  Steve Emmerson - Add length-checking of "cgrib"
//
// USAGE:    int g2_unpack2(unsigned char *cgrib, size_t sz, g2int *iofst,
//                      g2int *lencsec2, unsigned char **csec2)
//   INPUT ARGUMENT LIST:
//     cgrib    - char array containing Section 2 of the GRIB2 message
//     sz       - size of "cgrib" array in bytes
//     iofst    - Bit offset for the beginning of Section 2 in cgrib.
//
//   OUTPUT ARGUMENT LIST:      
//     iofst    - Bit offset at the end of Section 2, returned.
//     lencsec2 - Length (in octets) of Local Use data
//     csec2    - Pointer to a char array containing local use data
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Array passed is not section 2
//                6 = memory allocation error
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE: 
//
//$$$//*/
{

      g2int ierr,isecnum;
      g2int lensec,ipos,j;
      size_t bitsz = sz * 8;

      ierr=0;
      *lencsec2=0;
      *csec2=0;    /* NULL*/

      if (*iofst + 40 > bitsz) {
          fprintf(stderr, "Section too short to contain length and section "
                  "number");
          ierr=2;
          return(ierr);
      }
      gbit(cgrib,&lensec,*iofst,32);        /* Get Length of Section*/
      *iofst=*iofst+32;
      *lencsec2=lensec-5;
      gbit(cgrib,&isecnum,*iofst,8);         /* Get Section Number*/
      *iofst=*iofst+8;
      ipos=(*iofst/8);

      if ( isecnum != 2 ) {
         ierr=2;
         *lencsec2=0;
         fprintf(stderr,"g2_unpack2: Not Section 2 data.\n");
         return(ierr);
      }

      *csec2=(unsigned char *)malloc(*lencsec2+1);
      if (*csec2 == 0) {
         ierr=6;
         *lencsec2=0;
         return(ierr);
      }
      
      /*printf(" SAGIPO %d \n",(int)ipos);*/
      if (ipos + *lencsec2 > sz) {
          fprintf(stderr, "Section too short to contain required data");
          ierr=2;
          return(ierr);
      }
      for (j=0;j<*lencsec2;j++) {
         *(*csec2+j)=cgrib[ipos+j];
      }
      *iofst=*iofst+(*lencsec2*8);

      return(ierr);    /* End of Section 2 processing*/

}
Exemplo n.º 11
0
g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstmpl,
               g2int *mappdslen,g2float **coordlist,g2int *numcoord)
////$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack4 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 4 (Product Definition Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
//
// USAGE:    int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,
//                          g2int **ipdstmpl,g2int *mappdslen,
//                          g2float **coordlist,g2int *numcoord)
//   INPUT ARGUMENTS:
//     cgrib    - Char array containing Section 4 of the GRIB2 message
//     iofst    - Bit offset of the beginning of Section 4 in cgrib.
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset of the end of Section 4, returned.
//     ipdsnum  - Product Definition Template Number ( see Code Table 4.0)
//     ipdstmpl - Pointer to integer array containing the data values for 
//                the specified Product Definition
//                Template ( N=ipdsnum ).  Each element of this integer
//                array contains an entry (in the order specified) of Product
//                Defintion Template 4.N
//     mappdslen- Number of elements in ipdstmpl[].  i.e. number of entries
//                in Product Defintion Template 4.N  ( N=ipdsnum ).
//     coordlist- Pointer to real array containing floating point values 
//                intended to document
//                the vertical discretisation associated to model data
//                on hybrid coordinate vertical levels.  (part of Section 4)
//     numcoord - number of values in array coordlist.
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Not section 4
//                5 = "GRIB" message contains an undefined Product Definition
//                    Template.
//                6 = memory allocation error
//
// REMARKS: 
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$//
{

      g2int ierr,needext,i,j,nbits,isecnum;
      g2int lensec,isign,newlen;
      g2int *coordieee;
      g2int *lipdstmpl=0;
      g2float *lcoordlist;
      xxtemplate *mappds;

      ierr=0;
      *ipdstmpl=0;    // NULL
      *coordlist=0;    // NULL

      gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
      *iofst=*iofst+32;
      gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
      *iofst=*iofst+8;

      if ( isecnum != 4 ) {
         ierr=2;
         *numcoord=0;
         *mappdslen=0;
        // fprintf(stderr,"g2_unpack4: Not Section 4 data.\n");
         return(ierr);
      }

      gbit(cgrib,numcoord,*iofst,16);    // Get num of coordinate values
      *iofst=*iofst+16;
      gbit(cgrib,ipdsnum,*iofst,16);    // Get Prod. Def Template num.
      *iofst=*iofst+16;

      //   Get Product Definition Template
      mappds=getpdstemplate(*ipdsnum);
      if (mappds == 0) {       // undefine template
        ierr=5;
        *mappdslen=0;
        return(ierr);
      }
      *mappdslen=mappds->maplen;
      needext=mappds->needext;
      //
      //   Unpack each value into array ipdstmpl from the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mappds.
      //
      if (*mappdslen > 0) lipdstmpl=(g2int *)calloc(*mappdslen,sizeof(g2int));
      if (lipdstmpl == 0) {
         ierr=6;
         *mappdslen=0;
         *ipdstmpl=0;     //NULL
         if ( mappds != 0 ) free(mappds);
         return(ierr);
      }
      else {
         *ipdstmpl=lipdstmpl;
      }
      for (i=0;i<mappds->maplen;i++) {
        nbits=abs(mappds->map[i])*8;
        if ( mappds->map[i] >= 0 ) {
          gbit(cgrib,lipdstmpl+i,*iofst,nbits);
        }
        else {
          gbit(cgrib,&isign,*iofst,1);
          gbit(cgrib,lipdstmpl+i,*iofst+1,nbits-1);
          if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
        }
        *iofst=*iofst+nbits;
      }
      //
      //   Check to see if the Product Definition Template needs to be
      //   extended.
      //   The number of values in a specific template may vary
      //   depending on data specified in the "static" part of the
      //   template.
      //
      if ( needext ==1 ) {
        free(mappds);
        mappds=extpdstemplate(*ipdsnum,lipdstmpl);
        newlen=mappds->maplen+mappds->extlen;
        lipdstmpl=(g2int *)realloc(lipdstmpl,newlen*sizeof(g2int));
        *ipdstmpl=lipdstmpl;
        //   Unpack the rest of the Product Definition Template
        j=0;
        for (i=*mappdslen;i<newlen;i++) {
          nbits=abs(mappds->ext[j])*8;
          if ( mappds->ext[j] >= 0 ) {
            gbit(cgrib,lipdstmpl+i,*iofst,nbits);
          }
          else {
            gbit(cgrib,&isign,*iofst,1);
            gbit(cgrib,lipdstmpl+i,*iofst+1,nbits-1);
            if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
          }
          *iofst=*iofst+nbits;
          j++;
        }
        *mappdslen=newlen;
      }
      if( mappds->ext != 0 ) free(mappds->ext);
      if( mappds != 0 ) free(mappds);
      //
      //   Get Optional list of vertical coordinate values
      //   after the Product Definition Template, if necessary.
      //
      *coordlist=0;    // NULL
      if ( *numcoord != 0 ) {
         coordieee=(g2int *)calloc(*numcoord,sizeof(g2int));
         lcoordlist=(g2float *)calloc(*numcoord,sizeof(g2float));
         if (coordieee == 0 || lcoordlist == 0) {
            ierr=6;
            *numcoord=0;
            *coordlist=0;    // NULL
            if( coordieee != 0 ) free(coordieee);
            if( lcoordlist != 0 ) free(lcoordlist);
            return(ierr);
         }
         else {
            *coordlist=lcoordlist;
         }
        gbits(cgrib,coordieee,*iofst,32,0,*numcoord);
        rdieee(coordieee,*coordlist,*numcoord);
        free(coordieee);
        *iofst=*iofst+(32*(*numcoord));
      }
      
      return(ierr);    // End of Section 4 processing

}
Exemplo n.º 12
0
g2int g2_info(unsigned char *cgrib,int sz,g2int *listsec0,g2int *listsec1,
            g2int *numfields,g2int *numlocal)
/*$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_info 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
//
// ABSTRACT: This subroutine searches through a GRIB2 message and
//   returns the number of gridded fields found in the message and
//   the number (and maximum size) of Local Use Sections.
//   Also various checks  are performed
//   to see if the message is a valid GRIB2 message.
//
// PROGRAM HISTORY LOG:
// 2002-10-28  Gilbert
// ????-??-??  S. Chiswell modified to pass message size to ensure reading
//             doesn't go past message length
// 2013-05-28  Steve Emmerson modified to increase the level of verification of
//             the GRIB2 message structure.
//
// USAGE:   int g2_info(unsigned char *cgrib, g2int sz, g2int *listsec0,
//            g2int *listsec1, g2int *numfields,g2int *numlocal)
//   INPUT ARGUMENTS:
//     cgrib    - Character pointer to the GRIB2 message. May have junk in the
//                first 100 bytes before the "GRIB" sentinel and may have junk
//                after the valid GRIB message.
//     sz       - Length of "cgrib" data in bytes
//
//   OUTPUT ARGUMENTS:      
//     listsec0 - pointer to an array containing information decoded from 
//                GRIB Indicator Section 0.
//                Must be allocated with >= 3 elements.
//                listsec0[0]=Discipline-GRIB Master Table Number
//                            (see Code Table 0.0)
//                listsec0[1]=GRIB Edition Number (currently 2)
//                listsec0[2]=Length of GRIB message
//     listsec1 - pointer to an array containing information read from GRIB 
//                Identification Section 1.
//                Must be allocated with >= 13 elements.
//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
//                listsec1[1]=Id of orginating sub-centre (local table)
//                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
//                listsec1[3]=GRIB Local Tables Version Number 
//                listsec1[4]=Significance of Reference Time (Code Table 1.1)
//                listsec1[5]=Reference Time - Year (4 digits)
//                listsec1[6]=Reference Time - Month
//                listsec1[7]=Reference Time - Day
//                listsec1[8]=Reference Time - Hour
//                listsec1[9]=Reference Time - Minute
//                listsec1[10]=Reference Time - Second
//                listsec1[11]=Production status of data (Code Table 1.2)
//                listsec1[12]=Type of processed data (Code Table 1.3)
//     numfields- The number of gridded fields found in the GRIB message.
//                That is, the number of occurences of Sections 4 - 7.
//     numlocal - The number of Local Use Sections ( Section 2 ) found in 
//                the GRIB message.
//
//     RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                1 = Beginning characters "GRIB" not found.
//                2 = GRIB message is not Edition 2.
//                3 = Could not find Section 1 where expected.
//                4 = End string "7777" found prematurely
//                5 = End string "7777" not found at end of message.
//                6 = Invalid section number found.
//                7 = Invalid total or section length parameter in message
//
// REMARKS: This function ASSUMES that "CHAR_BIT == 8"
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$*/
{
      /*
       * NB: The following 3 parameters must be kept consonant.
       */
#     define MAP_SEC1_LEN 13
      const g2int mapsec1[MAP_SEC1_LEN]={2,2,1,1,1,2,1,1,1,1,1,1,1};
      const int MIN_LEN_SEC_1 = 16; /* minimum length, in bytes, of section 1 */

      g2int  i,j,istart,iofst,lengrib,lensec1;
      g2int ipos,isecnum,nbits,lensec;
      long remaining; /* number of bytes remaining to be decoded */

      *numlocal=0;
      *numfields=0;
/*
//  Check for beginning of GRIB message in the first 100 bytes
//  S. Chiswell, constrain to j<sz too*/
      istart=-1;
      for (j=0;j<sz-3 && j<100;j++) {
        if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' &&
            cgrib[j+3]=='B') {
          istart=j;
          break;
        }
      }
      if (istart == -1) {
        printf("g2_info:  Beginning characters GRIB not found.\n");
        return 1;
      }
      remaining = sz - istart;

      /*
       *  Unpack Section 0 - Indicator Section
       */
#     define LEN_SEC_0 16 /* The length, in bytes, of section 0. */
      if (LEN_SEC_0 > remaining) {
        printf("g2_info: Sanity check, bulletin too small to contain section 0: %ld\n",
                remaining);
        return 7;
      }
      iofst=8*(istart+6);
      gbit(cgrib,listsec0+0,iofst,8);     /* Discipline*/
      iofst=iofst+8;
      gbit(cgrib,listsec0+1,iofst,8);     /* GRIB edition number*/
      iofst=iofst+8;
      iofst=iofst+32;
      gbit(cgrib,&lengrib,iofst,32);        /* Length of GRIB message*/
      iofst=iofst+32;
      listsec0[2]=lengrib;

      /*
       * Validate length of GRIB message. S. Chiswell & S. Emmerson.
       */
      if (lengrib < LEN_SEC_0 || lengrib > remaining) {
        printf("g2_info: Sanity check, grib length too big or too small: %ld\n",
                (long)lengrib);
        return 7;
      }

      ipos=istart+LEN_SEC_0;
      remaining = lengrib - LEN_SEC_0;

      /*
       *  Currently handles only GRIB Edition 2.
       */
      if (listsec0[1] != 2) {
        printf("g2_info: can only decode GRIB edition 2.\n");
        return 2;
      }

      /*
       *  Unpack Section 1 - Identification Section
       */
      if (MIN_LEN_SEC_1 > remaining) {
          printf("g2_info: Sanity check, bulletin too small to contain section 1: %ld\n",
                  remaining);
      }
      gbit(cgrib,&lensec1,iofst,32);        /* Length of Section 1*/
      iofst=iofst+32;

      /*
       * Validate length of section 1. S. Emmerson.
       */
      if (lensec1 < MIN_LEN_SEC_1 || lensec1 > remaining) {
        printf("g2_info: Sanity check, section 1 length too big or too small: %ld\n",
                (long)lensec1);
        return 7;
      }

      /*
       * Decode and validate the section number.
       */
      gbit(cgrib,&isecnum,iofst,8);
      iofst=iofst+8;
      if (isecnum != 1) {
        printf("g2_info: Could not find section 1.\n");
        return 3;
      }

      /*
       *   Unpack each input value in array listsec1 into the
       *   the appropriate number of octets, which are specified in
       *   corresponding entries in array mapsec1.
       */
      for (i=0;i<MAP_SEC1_LEN;i++) {
        nbits=mapsec1[i]*8;
        gbit(cgrib,listsec1+i,iofst,nbits);
        iofst=iofst+nbits;
      }

      ipos += lensec1;
      remaining -= lensec1;

      /*
       *  Loop through the remaining sections to see if they are valid.
       *  Also count the number of times Section 2
       *  and Section 4 appear.
       */
      while (remaining >= 4) {
        if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' &&
            cgrib[ipos+3]=='7') {
          remaining -= 4;
          if (remaining) {
            printf("g2_info: '7777' found, but not where expected.\n");
            return 4;
          }
          return 0;
        }

        /*
         * Minimum length of a section in bytes (section length & section number)
         */
#       define MIN_LEN_SEC 5
        if (remaining < MIN_LEN_SEC) {
            printf("g2_info: Sanity check, section too small: %ld\n",
                    remaining);
            return 7;
        }
        
        iofst=ipos*8;

        /*
         * Decode and validate the section length.
         */
        gbit(cgrib,&lensec,iofst,32);
        iofst=iofst+32;
        if (lensec < MIN_LEN_SEC || lensec > remaining) {
          printf("g2_info: Sanity check, section length too big or too small: %ld\n",
                  (long)lensec);
          return 7;
        }

        /*
         * Decode and validate the section number.
         */
        gbit(cgrib,&isecnum,iofst,8);
        iofst=iofst+8;
        if ( isecnum>=2 && isecnum<=7 ) {
           if (isecnum == 2) {    /* Local Section 2*/
              /*   increment counter for total number of local sections found*/
              (*numlocal)++;
           }
           else if (isecnum == 4) {
              /*   increment counter for total number of fields found*/
              (*numfields)++;
           }
        }
        else {
           printf("g2_info: Invalid section number found in GRIB message: %ld\n",
                   (long)isecnum);
           return 6;
        }

        ipos += lensec;                 /* Update beginning of section pointer*/
        remaining -= lensec;
      } /* while sufficient bytes remain */

      if (remaining) {
        printf("g2_info: '7777'  not found at end of GRIB message.\n");
        return 5;
      }

      return 0;

}
Exemplo n.º 13
0
g2int g2_unpack6(unsigned char *cgrib,size_t sz,g2int *iofst,g2int ngpts,
        g2int *ibmap, g2int **bmap)
/*$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack6 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 6 (Bit-Map Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
// 2014-02-25  Steve Emmerson (UCAR/Unidata)  Add length-checking of "cgrib"
//                                            array
//
// USAGE:    int g2_unpack6(unsigned char *cgrib,size_t sz, g2int *iofst,
//                      g2int ngpts, g2int *ibmap,g2int **bmap)
//   INPUT ARGUMENTS:
//     cgrib    - char array containing Section 6 of the GRIB2 message
//     sz       - Size of "cgrib" array in bytes
//     iofst    - Bit offset of the beginning of Section 6 in cgrib.
//     ngpts    - Number of grid points specified in the bit-map
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset at the end of Section 6, returned.
//     ibmap    - Bitmap indicator ( see Code Table 6.0 )
//                0 = bitmap applies and is included in Section 6.
//                1-253 = Predefined bitmap applies
//                254 = Previously defined bitmap applies to this field
//                255 = Bit map does not apply to this product.
//     bmap     - Pointer to an integer array containing decoded bitmap. 
//                ( if ibmap=0 )
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Not Section 6
//                4 = Unrecognized pre-defined bit-map.
//                6 = memory allocation error
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$*/
{
      g2int j,ierr,isecnum;
      g2int *lbmap=0;
      g2int *intbmap;
      size_t bitsz = sz * 8;

      ierr=0;
      *bmap=0;    /*NULL*/

      if (*iofst + 40 > bitsz)
          return 2;
      *iofst=*iofst+32;    /* skip Length of Section*/
      gbit(cgrib,&isecnum,*iofst,8);         /* Get Section Number*/
      *iofst=*iofst+8; 

      if ( isecnum != 6 ) {
         ierr=2;
         fprintf(stderr,"g2_unpack6: Not Section 6 data.\n");
         return(ierr);
      }

      if (*iofst + 8 > bitsz)
          return 2;
      gbit(cgrib,ibmap,*iofst,8);    /* Get bit-map indicator*/
      *iofst=*iofst+8;

      if (*ibmap == 0) {               /* Unpack bitmap*/
         if (ngpts > 0) lbmap=(g2int *)calloc(ngpts,sizeof(g2int));
         if (lbmap == 0) {
            ierr=6;
            return(ierr);
         }
         else {
            *bmap=lbmap;
         }
         intbmap=(g2int *)calloc(ngpts,sizeof(g2int));  
         if (*iofst + ngpts > bitsz) {
           if (intbmap) free(intbmap);
           return 2;
         }
         gbits(cgrib,intbmap,*iofst,1,0,ngpts);
         *iofst=*iofst+ngpts;
         for (j=0;j<ngpts;j++) {
           lbmap[j]=(g2int)intbmap[j];
         }
         free(intbmap);
/*      else if (*ibmap.eq.254)               ! Use previous bitmap
//        return(ierr);
//      else if (*ibmap.eq.255)               ! No bitmap in message
//        bmap(1:ngpts)=.true.
//      else {
//        print *,'gf_unpack6: Predefined bitmap ',*ibmap,' not recognized.'
//        ierr=4;*/
      }
      
      return(ierr);    /* End of Section 6 processing*/

}
Exemplo n.º 14
0
g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl,
                         g2int *mapgridlen,g2int **ideflist,g2int *idefnum)
////$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack3 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This routine unpacks Section 3 (Grid Definition Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
//
// USAGE:    int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,
//                          g2int **igdstmpl,g2int *mapgridlen,
//                          g2int **ideflist,g2int *idefnum)
//   INPUT ARGUMENTS:
//     cgrib    - Char array ontaining Section 3 of the GRIB2 message
//     iofst    - Bit offset for the beginning of Section 3 in cgrib.
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset at the end of Section 3, returned.
//     igds     - Contains information read from the appropriate GRIB Grid 
//                Definition Section 3 for the field being returned.
//                igds[0]=Source of grid definition (see Code Table 3.0)
//                igds[1]=Number of grid points in the defined grid.
//                igds[2]=Number of octets needed for each 
//                            additional grid points definition.  
//                            Used to define number of
//                            points in each row ( or column ) for
//                            non-regular grids.  
//                            = 0, if using regular grid.
//                igds[3]=Interpretation of list for optional points 
//                            definition.  (Code Table 3.11)
//                igds[4]=Grid Definition Template Number (Code Table 3.1)
//     igdstmpl - Pointer to integer array containing the data values for 
//                the specified Grid Definition
//                Template ( NN=igds[4] ).  Each element of this integer 
//                array contains an entry (in the order specified) of Grid
//                Defintion Template 3.NN
//     mapgridlen- Number of elements in igdstmpl[].  i.e. number of entries
//                in Grid Defintion Template 3.NN  ( NN=igds[4] ).
//     ideflist - (Used if igds[2] .ne. 0)  Pointer to integer array containing
//                the number of grid points contained in each row ( or column ).
//                (part of Section 3)
//     idefnum  - (Used if igds[2] .ne. 0)  The number of entries
//                in array ideflist.  i.e. number of rows ( or columns )
//                for which optional grid points are defined.
//     ierr     - Error return code.
//                0 = no error
//                2 = Not Section 3
//                5 = "GRIB" message contains an undefined Grid Definition
//                    Template.
//                6 = memory allocation error
//
// REMARKS: 
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$

{
      g2int ierr,i,j,nbits,isecnum;
      g2int lensec,ibyttem=0,isign,newlen;
      g2int *ligds,*ligdstmpl=0,*lideflist=0;
      xxtemplate *mapgrid;

      ierr=0;
      *igds=0;       // NULL
      *igdstmpl=0;       // NULL
      *ideflist=0;       // NULL

      gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
      *iofst=*iofst+32;
      gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
      *iofst=*iofst+8;

      if ( isecnum != 3 ) {
         ierr=2;
         *idefnum=0;
         *mapgridlen=0;
        // fprintf(stderr,"g2_unpack3: Not Section 3 data.\n");
         return(ierr);
      }

      ligds=(g2int *)calloc(5,sizeof(g2int));
      *igds=ligds;

      gbit(cgrib,ligds+0,*iofst,8);     // Get source of Grid def.
      *iofst=*iofst+8;
      gbit(cgrib,ligds+1,*iofst,32);    // Get number of grid pts.
      *iofst=*iofst+32;
      gbit(cgrib,ligds+2,*iofst,8);     // Get num octets for opt. list
      *iofst=*iofst+8;
      gbit(cgrib,ligds+3,*iofst,8);     // Get interpret. for opt. list
      *iofst=*iofst+8;
      gbit(cgrib,ligds+4,*iofst,16);    // Get Grid Def Template num.
      *iofst=*iofst+16;

      if (ligds[4] != 65535) {
        //   Get Grid Definition Template
        mapgrid=getgridtemplate(ligds[4]);
        if (mapgrid == 0) {         // undefined template
          ierr=5;
          return(ierr);
        }
        *mapgridlen=mapgrid->maplen;
        //
        //   Unpack each value into array igdstmpl from the
        //   the appropriate number of octets, which are specified in
        //   corresponding entries in array mapgrid.
        //
        if (*mapgridlen > 0) {
           ligdstmpl=0;
           ligdstmpl=(g2int *)calloc(*mapgridlen,sizeof(g2int));
           if (ligdstmpl == 0) {
              ierr=6;
              *mapgridlen=0;
              *igdstmpl=0;    //NULL
              if( mapgrid != 0 ) free(mapgrid);
              return(ierr);
           }
           else {
              *igdstmpl=ligdstmpl;
           }
        }
        ibyttem=0;
        for (i=0;i<*mapgridlen;i++) {
          nbits=abs(mapgrid->map[i])*8;
          if ( mapgrid->map[i] >= 0 ) {
            gbit(cgrib,ligdstmpl+i,*iofst,nbits);
          }
          else {
            gbit(cgrib,&isign,*iofst,1);
            gbit(cgrib,ligdstmpl+i,*iofst+1,nbits-1);
            if (isign == 1) ligdstmpl[i]=-1*ligdstmpl[i];
          }
          *iofst=*iofst+nbits;
          ibyttem=ibyttem+abs(mapgrid->map[i]);
        }
        //
        //   Check to see if the Grid Definition Template needs to be
        //   extended.
        //   The number of values in a specific template may vary
        //   depending on data specified in the "static" part of the
        //   template.
        //
        if ( mapgrid->needext == 1 ) {
          free(mapgrid);
          mapgrid=extgridtemplate(ligds[4],ligdstmpl);
          //   Unpack the rest of the Grid Definition Template
          newlen=mapgrid->maplen+mapgrid->extlen;
          ligdstmpl=(g2int *)realloc(ligdstmpl,newlen*sizeof(g2int));
          *igdstmpl=ligdstmpl;
          j=0;
          for (i=*mapgridlen;i<newlen;i++) {
            nbits=abs(mapgrid->ext[j])*8;
            if ( mapgrid->ext[j] >= 0 ) {
              gbit(cgrib,ligdstmpl+i,*iofst,nbits);
            }
            else {
              gbit(cgrib,&isign,*iofst,1);
              gbit(cgrib,ligdstmpl+i,*iofst+1,nbits-1);
              if (isign == 1) ligdstmpl[i]=-1*ligdstmpl[i];
            }
            *iofst=*iofst+nbits;
            ibyttem=ibyttem+abs(mapgrid->ext[j]);
            j++;
          }
          *mapgridlen=newlen;
        }
        if( mapgrid->ext != 0 ) free(mapgrid->ext);
        if( mapgrid != 0 ) free(mapgrid);
      }
      else {              // No Grid Definition Template
        *mapgridlen=0;
        *igdstmpl=0;
      }
      //
      //   Unpack optional list of numbers defining number of points
      //   in each row or column, if included.  This is used for non regular
      //   grids.
      //
      if ( ligds[2] != 0 ) {
         nbits=ligds[2]*8;
         *idefnum=(lensec-14-ibyttem)/ligds[2];
         if (*idefnum > 0) lideflist=(g2int *)calloc(*idefnum,sizeof(g2int));
         if (lideflist == 0) {
            ierr=6;
            *idefnum=0;
            *ideflist=0;   //NULL
            return(ierr);
         }
         else {
            *ideflist=lideflist;
         }
         gbits(cgrib,lideflist,*iofst,nbits,0,*idefnum);
         *iofst=*iofst+(nbits*(*idefnum));
      }
      else {
         *idefnum=0;
         *ideflist=0;    // NULL
      }
      
      return(ierr);    // End of Section 3 processing
}
Exemplo n.º 15
0
g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflist,g2int idefnum)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_addgrid 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
//
// ABSTRACT: This routine packs up a Grid Definition Section (Section 3) 
//   and adds it to a GRIB2 message.  It is used with routines "g2_create",
//   "g2_addlocal", "g2_addfield",
//   and "g2_gribend" to create a complete GRIB2 message.
//   g2_create must be called first to initialize a new GRIB2 message.
//
// PROGRAM HISTORY LOG:
// 2002-11-01  Gilbert
// 2009-01-14  Vuong     Changed structure name template to gtemplate
//
// USAGE:    int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,
//                          g2int *ideflist,g2int idefnum)
//   INPUT ARGUMENTS:
//     cgrib    - Char array that contains the GRIB2 message to which
//                section should be added.
//     igds     - Contains information needed for GRIB Grid Definition Section 3
//                Must be dimensioned >= 5.
//                igds[0]=Source of grid definition (see Code Table 3.0)
//                igds[1]=Number of grid points in the defined grid.
//                igds[2]=Number of octets needed for each 
//                            additional grid points definition.  
//                            Used to define number of
//                            points in each row ( or column ) for
//                            non-regular grids.  
//                            = 0, if using regular grid.
//                igds[3]=Interpretation of list for optional points 
//                            definition.  (Code Table 3.11)
//                igds[4]=Grid Definition Template Number (Code Table 3.1)
//     igdstmpl - Contains the data values for the specified Grid Definition
//                Template ( NN=igds[4] ).  Each element of this integer 
//                array contains an entry (in the order specified) of Grid
//                Defintion Template 3.NN
//     ideflist - (Used if igds[2] != 0)  This array contains the
//                number of grid points contained in each row ( or column )
//      idefnum - (Used if igds[2] != 0)  The number of entries
//                in array ideflist.  i.e. number of rows ( or columns )
//                for which optional grid points are defined.
//
//   OUTPUT ARGUMENTS:      
//     cgrib    - Char array to contain the updated GRIB2 message.
//                Must be allocated large enough to store the entire
//                GRIB2 message.
//
//   RETURN VALUES:
//     ierr     - Return code.
//              > 0 = Current size of updated GRIB2 message
//               -1 = GRIB message was not initialized.  Need to call
//                    routine gribcreate first.
//               -2 = GRIB message already complete.  Cannot add new section.
//               -3 = Sum of Section byte counts doesn't add to total byte count
//               -4 = Previous Section was not 1, 2 or 7.
//               -5 = Could not find requested Grid Definition Template.
//
// REMARKS: Note that the Grid Def Section ( Section 3 ) can only follow
//          Section 1, 2 or Section 7 in a GRIB2 message.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$
{

      g2int ierr;
      static unsigned char G=0x47;       // 'G'
      static unsigned char R=0x52;       // 'R'
      static unsigned char I=0x49;       // 'I'
      static unsigned char B=0x42;       // 'B'
      static unsigned char seven=0x37;   // '7'

      static g2int one=1,three=3,miss=65535;
      g2int   lensec3,iofst,ibeg,lencurr,len;
      g2int   i,j,temp,ilen,isecnum,nbits;
      gtemplate *mapgrid=0;
 
      ierr=0;
//
//  Check to see if beginning of GRIB message exists
//
      if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
        // printf("g2_addgrid: GRIB not found in given message.\n");
        // printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB messge.\n");
        ierr=-1;
        return(ierr);
      }
//
//  Get current length of GRIB message
//  
      gbit(cgrib,&lencurr,96,32);
//
//  Check to see if GRIB message is already complete
//  
      if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
           cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
        // printf("g2_addgrid: GRIB message already complete.  Cannot add new section.\n");
        ierr=-2;
        return(ierr);
      }
//
//  Loop through all current sections of the GRIB message to
//  find the last section number.
//
      len=16;    // length of Section 0
      for (;;) { 
      //    Get section number and length of next section
        iofst=len*8;
        gbit(cgrib,&ilen,iofst,32);
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);
        len=len+ilen;
      //    Exit loop if last section reached
        if ( len == lencurr ) break;
      //    If byte count for each section doesn't match current
      //    total length, then there is a problem.
        if ( len > lencurr ) {
          // printf("g2_addgrid: Section byte counts don''t add to total.\n");
          // printf("g2_addgrid: Sum of section byte counts = %ld\n",len);
          // printf("g2_addgrid: Total byte count in Section 0 = %ld\n",lencurr);
          ierr=-3;
          return(ierr);
        }
      }
//
//  Section 3 can only be added after sections 1, 2 and 7.
//
      if ( (isecnum!=1) && (isecnum!=2) && (isecnum!=7) ) {
        // printf("g2_addgrid: Section 3 can only be added after Section 1, 2 or 7.\n");
        // printf("g2_addgrid: Section ',isecnum,' was the last found in given GRIB message.\n");
        ierr=-4;
        return(ierr);
      }
//
//  Add Section 3  - Grid Definition Section
//
      ibeg=lencurr*8;        //   Calculate offset for beginning of section 3
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&three,iofst,8);     // Store section number ( 3 )
      iofst=iofst+8;
      sbit(cgrib,igds+0,iofst,8);     // Store source of Grid def.
      iofst=iofst+8;
      sbit(cgrib,igds+1,iofst,32);    // Store number of data pts.
      iofst=iofst+32;
      sbit(cgrib,igds+2,iofst,8);     // Store number of extra octets.
      iofst=iofst+8;
      sbit(cgrib,igds+3,iofst,8);     // Store interp. of extra octets.
      iofst=iofst+8;
      //   if Octet 6 is not equal to zero, Grid Definition Template may
      //   not be supplied.
      if ( igds[0] == 0 )
        sbit(cgrib,igds+4,iofst,16);  // Store Grid Def Template num.
      else
        sbit(cgrib,&miss,iofst,16);   // Store missing value as Grid Def Template num.
      iofst=iofst+16;
      //
      //   Get Grid Definition Template
      //
      if (igds[0] == 0) {
        mapgrid=getgridtemplate(igds[4]);
        if (mapgrid == 0) {       // undefined template
          ierr=-5;
          return(ierr);
        }
        //
        //   Extend the Grid Definition Template, if necessary.
        //   The number of values in a specific template may vary
        //   depending on data specified in the "static" part of the
        //   template.
        //
        if ( mapgrid->needext ) {
          free(mapgrid);
          mapgrid=extgridtemplate(igds[4],igdstmpl);
        }
      }
      //
      //   Pack up each input value in array igdstmpl into the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapgrid.
      //
      for (i=0;i<mapgrid->maplen;i++) {
        nbits=abs(mapgrid->map[i])*8;
        if ( (mapgrid->map[i] >= 0) || (igdstmpl[i] >= 0) )
          sbit(cgrib,igdstmpl+i,iofst,nbits);
        else {
          sbit(cgrib,&one,iofst,1);
          temp=abs(igdstmpl[i]);
          sbit(cgrib,&temp,iofst+1,nbits-1);
        }
        iofst=iofst+nbits;
      }
      //  Pack template extension, if appropriate
      j=mapgrid->maplen;
      if ( mapgrid->needext && (mapgrid->extlen > 0) ) {
         for (i=0;i<mapgrid->extlen;i++) {
           nbits=abs(mapgrid->ext[i])*8;
           if ( (mapgrid->ext[i] >= 0) || (igdstmpl[j] >= 0) )
             sbit(cgrib,igdstmpl+j,iofst,nbits);
           else {
             sbit(cgrib,&one,iofst,1);
             temp=abs(igdstmpl[j]);
             sbit(cgrib,&temp,iofst+1,nbits-1);
           }
           iofst=iofst+nbits;
           j++;
         }
      }
      free(mapgrid);
      //
      //   If requested,
      //   Insert optional list of numbers defining number of points
      //   in each row or column.  This is used for non regular
      //   grids.
      //
      if ( igds[2] != 0 ) {
         nbits=igds[2]*8;
         sbits(cgrib,ideflist,iofst,nbits,0,idefnum);
         iofst=iofst+(nbits*idefnum);
      }
      //
      //   Calculate length of section 3 and store it in octets
      //   1-4 of section 3.
      //
      lensec3=(iofst-ibeg)/8;
      sbit(cgrib,&lensec3,ibeg,32);

//
//  Update current byte total of message in Section 0
//
      lencurr+=lensec3;
      sbit(cgrib,&lencurr,96,32);

      return(lencurr);

}
Exemplo n.º 16
0
g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
                gribfield **gfld)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_getfld 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
//
// ABSTRACT: This subroutine returns all the metadata, template values, 
//   Bit-map ( if applicable ), and the unpacked data for a given data
//   field.  All of the information returned is stored in a gribfield
//   structure, which is defined in file grib2.h.
//   Users of this routine will need to include "grib2.h" in their source
//   code that calls this routine.  Each component of the gribfield
//   struct is also described in the OUTPUT ARGUMENTS section below.
//
//   Since there can be multiple data fields packed into a GRIB2
//   message, the calling routine indicates which field is being requested
//   with the ifldnum argument.
//
// PROGRAM HISTORY LOG:
// 2002-10-28  Gilbert
//
// USAGE:    #include "grib2.h"
//           int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,
//                         g2int expand,gribfield **gfld)
//   INPUT ARGUMENTS:
//     cgrib    - Character pointer to the GRIB2 message
//     ifldnum  - Specifies which field in the GRIB2 message to return.
//     unpack   - Boolean value indicating whether to unpack bitmap/data field
//                1 = unpack bitmap (if present) and data values
//                0 = do not unpack bitmap and data values
//     expand   - Boolean value indicating whether the data points should be 
//                expanded to the correspond grid, if a bit-map is present.
//                1 = if possible, expand data field to grid, inserting zero 
//                    values at gridpoints that are bitmapped out. 
//                    (SEE REMARKS2)
//                0 = do not expand data field, leaving it an array of
//                    consecutive data points for each "1" in the bitmap.
//                This argument is ignored if unpack == 0 OR if the
//                returned field does not contain a bit-map.
//
//   OUTPUT ARGUMENT:      
//     gribfield gfld; - pointer to structure gribfield containing
//                       all decoded data for the data field.
// 
//        gfld->version = GRIB edition number ( currently 2 )
//        gfld->discipline = Message Discipline ( see Code Table 0.0 )
//        gfld->idsect = Contains the entries in the Identification
//                        Section ( Section 1 )
//                        This element is a pointer to an array
//                        that holds the data.
//            gfld->idsect[0]  = Identification of originating Centre
//                                    ( see Common Code Table C-1 )
//                             7 - US National Weather Service
//            gfld->idsect[1]  = Identification of originating Sub-centre
//            gfld->idsect[2]  = GRIB Master Tables Version Number
//                                    ( see Code Table 1.0 )
//                             0 - Experimental
//                             1 - Initial operational version number
//            gfld->idsect[3]  = GRIB Local Tables Version Number
//                                    ( see Code Table 1.1 )
//                             0     - Local tables not used
//                             1-254 - Number of local tables version used
//            gfld->idsect[4]  = Significance of Reference Time (Code Table 1.2)
//                             0 - Analysis
//                             1 - Start of forecast
//                             2 - Verifying time of forecast
//                             3 - Observation time
//            gfld->idsect[5]  = Year ( 4 digits )
//            gfld->idsect[6]  = Month
//            gfld->idsect[7)  = Day
//            gfld->idsect[8]  = Hour
//            gfld->idsect[9]  = Minute
//            gfld->idsect[10]  = Second
//            gfld->idsect[11]  = Production status of processed data
//                                    ( see Code Table 1.3 )
//                              0 - Operational products
//                              1 - Operational test products
//                              2 - Research products
//                              3 - Re-analysis products
//            gfld->idsect[12]  = Type of processed data ( see Code Table 1.4 )
//                              0  - Analysis products
//                              1  - Forecast products
//                              2  - Analysis and forecast products
//                              3  - Control forecast products
//                              4  - Perturbed forecast products
//                              5  - Control and perturbed forecast products
//                              6  - Processed satellite observations
//                              7  - Processed radar observations
//        gfld->idsectlen = Number of elements in gfld->idsect[].
//        gfld->local   = Pointer to character array containing contents
//                       of Local Section 2, if included
//        gfld->locallen = length of array gfld->local[]
//        gfld->ifldnum = field number within GRIB message
//        gfld->griddef = Source of grid definition (see Code Table 3.0)
//                      0 - Specified in Code table 3.1
//                      1 - Predetermined grid Defined by originating centre
//        gfld->ngrdpts = Number of grid points in the defined grid.
//        gfld->numoct_opt = Number of octets needed for each
//                          additional grid points definition.
//                          Used to define number of
//                          points in each row ( or column ) for
//                          non-regular grids.
//                          = 0, if using regular grid.
//        gfld->interp_opt = Interpretation of list for optional points
//                          definition.  (Code Table 3.11)
//        gfld->igdtnum = Grid Definition Template Number (Code Table 3.1)
//        gfld->igdtmpl  = Contains the data values for the specified Grid
//                         Definition Template ( NN=gfld->igdtnum ).  Each
//                         element of this integer array contains an entry (in
//                         the order specified) of Grid Defintion Template 3.NN
//                         This element is a pointer to an array
//                         that holds the data.
//        gfld->igdtlen = Number of elements in gfld->igdtmpl[].  i.e. number of
//                       entries in Grid Defintion Template 3.NN
//                       ( NN=gfld->igdtnum ).
//        gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array
//                          contains the number of grid points contained in
//                          each row ( or column ).  (part of Section 3)
//                          This element is a pointer to an array
//                          that holds the data.  This pointer is nullified
//                          if gfld->numoct_opt=0.
//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0) 
//                        The number of entries
//                       in array ideflist.  i.e. number of rows ( or columns )
//                       for which optional grid points are defined.  This value
//                       is set to zero, if gfld->numoct_opt=0.
//        gfdl->ipdtnum = Product Definition Template Number(see Code Table 4.0)
//        gfld->ipdtmpl  = Contains the data values for the specified Product
//                         Definition Template ( N=gfdl->ipdtnum ). Each element
//                         of this integer array contains an entry (in the
//                         order specified) of Product Defintion Template 4.N.
//                         This element is a pointer to an array
//                         that holds the data.
//        gfld->ipdtlen = Number of elements in gfld->ipdtmpl[].  i.e. number of
//                       entries in Product Defintion Template 4.N
//                       ( N=gfdl->ipdtnum ).
//        gfld->coord_list  = Real array containing floating point values
//                            intended to document the vertical discretisation
//                            associated to model data on hybrid coordinate
//                            vertical levels.  (part of Section 4)
//                            This element is a pointer to an array
//                            that holds the data.
//        gfld->num_coord = number of values in array gfld->coord_list[].
//        gfld->ndpts = Number of data points unpacked and returned.
//        gfld->idrtnum = Data Representation Template Number
//                       ( see Code Table 5.0)
//        gfld->idrtmpl  = Contains the data values for the specified Data
//                         Representation Template ( N=gfld->idrtnum ).  Each
//                         element of this integer array contains an entry
//                         (in the order specified) of Product Defintion
//                         Template 5.N.
//                         This element is a pointer to an array
//                         that holds the data.
//        gfld->idrtlen = Number of elements in gfld->idrtmpl[].  i.e. number
//                       of entries in Data Representation Template 5.N
//                       ( N=gfld->idrtnum ).
//        gfld->unpacked = logical value indicating whether the bitmap and
//                        data values were unpacked.  If false,
//                        gfld->bmap and gfld->fld pointers are nullified.
//        gfld->expanded = Logical value indicating whether the data field 
//                         was expanded to the grid in the case where a 
//                         bit-map is present.  If true, the data points in
//                         gfld->fld match the grid points and zeros were 
//                         inserted at grid points where data was bit-mapped
//                         out.  If false, the data values in gfld->fld were
//                         not expanded to the grid and are just a consecutive
//                         array of data points corresponding to each value of
//                         "1" in gfld->bmap.
//        gfld->ibmap = Bitmap indicator ( see Code Table 6.0 )
//                     0 = bitmap applies and is included in Section 6.
//                     1-253 = Predefined bitmap applies
//                     254 = Previously defined bitmap applies to this field
//                     255 = Bit map does not apply to this product.
//        gfld->bmap  = integer array containing decoded bitmap,
//                      if gfld->ibmap=0 or gfld->ibap=254.  Otherwise nullified
//                      This element is a pointer to an array
//                      that holds the data.
//        gfld->fld  = Array of gfld->ndpts unpacked data points.
//                     This element is a pointer to an array
//                     that holds the data.
//
// 
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                1 = Beginning characters "GRIB" not found.
//                2 = GRIB message is not Edition 2.
//                3 = The data field request number was not positive.
//                4 = End string "7777" found, but not where expected.
//                6 = GRIB message did not contain the requested number of
//                    data fields.
//                7 = End string "7777" not found at end of message.
//                8 = Unrecognized Section encountered.
//                9 = Data Representation Template 5.NN not yet implemented.
//               15 = Error unpacking Section 1.
//               16 = Error unpacking Section 2.
//               10 = Error unpacking Section 3.
//               11 = Error unpacking Section 4.
//               12 = Error unpacking Section 5.
//               13 = Error unpacking Section 6.
//               14 = Error unpacking Section 7.
//               17 = Previous bitmap specified, yet none exists.
//
// REMARKS: Note that struct gribfield is allocated by this routine and it
//          also contains pointers to many arrays of data that were allocated
//          during decoding.  Users are encouraged to free up this memory, 
//          when it is no longer needed, by an explicit call to routine g2_free.
//          EXAMPLE:
//              #include "grib2.h"
//              gribfield *gfld;
//              ret=g2_getfld(cgrib,1,1,1,&gfld);
//                ...
//              g2_free(gfld);
//
//          Routine g2_info can be used to first determine
//          how many data fields exist in a given GRIB message.
//
// REMARKS2: It may not always be possible to expand a bit-mapped data field.
//           If a pre-defined bit-map is used and not included in the GRIB2
//           message itself, this routine would not have the necessary 
//           information to expand the data.  In this case, gfld->expanded would
//           would be set to 0 (false), regardless of the value of input 
//           argument expand.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$
{
    
      g2int have3,have4,have5,have6,have7,ierr,jerr;
      g2int numfld,j,n,istart,iofst,ipos;
      g2int disc,ver,lensec0,lengrib,lensec,isecnum;
      g2int  *igds;
      g2int *bmpsave;
      g2float *newfld;
      gribfield  *lgfld;

      have3=0;
      have4=0;
      have5=0;
      have6=0;
      have7=0;
      ierr=0;
      numfld=0;

      lgfld=(gribfield *)malloc(sizeof(gribfield));
      *gfld=lgfld;

      lgfld->locallen=0;
      lgfld->idsect=0;
      lgfld->local=0;
      lgfld->list_opt=0;
      lgfld->igdtmpl=0;
      lgfld->ipdtmpl=0;
      lgfld->idrtmpl=0;
      lgfld->coord_list=0;
      lgfld->bmap=0;
      lgfld->fld=0;
//
//  Check for valid request number
//  
      if (ifldnum <= 0) {
        printf("g2_getfld: Request for field number must be positive.\n");
        ierr=3;
        return(ierr);
      }
//
//  Check for beginning of GRIB message in the first 100 bytes
//
      istart=-1;
      for (j=0;j<100;j++) {
        if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' && 
            cgrib[j+3]=='B') {
          istart=j;
          break;
        }
      }
      if (istart == -1) {
        printf("g2_getfld:  Beginning characters GRIB not found.\n");
        ierr=1;
        return(ierr);
      }
//
//  Unpack Section 0 - Indicator Section 
//
      iofst=8*(istart+6);
      gbit(cgrib,&disc,iofst,8);     // Discipline
      iofst=iofst+8;
      gbit(cgrib,&ver,iofst,8);     // GRIB edition number
      iofst=iofst+8;
      iofst=iofst+32;
      gbit(cgrib,&lengrib,iofst,32);        // Length of GRIB message
      iofst=iofst+32;
      lensec0=16;
      ipos=istart+lensec0;
//
//  Currently handles only GRIB Edition 2.
//  
      if (ver != 2) {
        printf("g2_getfld: can only decode GRIB edition 2.\n");
        ierr=2;
        return(ierr);
      }
//
//  Loop through the remaining sections keeping track of the 
//  length of each.  Also keep the latest Grid Definition Section info.
//  Unpack the requested field number.
//
      for (;;) {
        //    Check to see if we are at end of GRIB message
        if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' && 
            cgrib[ipos+3]=='7') {
          ipos=ipos+4;
          //    If end of GRIB message not where expected, issue error
          if (ipos != (istart+lengrib)) {
            printf("g2_getfld: '7777' found, but not where expected.\n");
            ierr=4;
            return(ierr);
          }
          break;
        }
        //     Get length of Section and Section number
        iofst=(ipos-1)*8;
        iofst=ipos*8;
        gbit(cgrib,&lensec,iofst,32);        // Get Length of Section
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);         // Get Section number
        iofst=iofst+8;
        //printf(" lensec= %d    secnum= %d \n",lensec,isecnum);
        //
        //  Check to see if section number is valid
        //
        if ( isecnum<1 || isecnum>7 ) {
          printf("g2_getfld: Unrecognized Section Encountered=%d\n",isecnum);
          ierr=8;
          return(ierr);
        }
        //
        //   If found Section 1, decode elements in Identification Section
        //
        if (isecnum == 1) {
          iofst=iofst-40;       // reset offset to beginning of section
          jerr=g2_unpack1(cgrib,&iofst,&lgfld->idsect,&lgfld->idsectlen);
          if (jerr !=0 ) {
            ierr=15;
            return(ierr);
          }
        }
        //
        //   If found Section 2, Grab local section
        //   Save in case this is the latest one before the requested field.
        //
        if (isecnum == 2) {
          iofst=iofst-40;       // reset offset to beginning of section
          if (lgfld->local!=0) free(lgfld->local);
          jerr=g2_unpack2(cgrib,&iofst,&lgfld->locallen,&lgfld->local);
          if (jerr != 0) {
            ierr=16;
            return(ierr);
          }
        }
        //
        //   If found Section 3, unpack the GDS info using the 
        //   appropriate template.  Save in case this is the latest
        //   grid before the requested field.
        //
        if (isecnum == 3) {
          iofst=iofst-40;       // reset offset to beginning of section
          if (lgfld->igdtmpl!=0) free(lgfld->igdtmpl);
          if (lgfld->list_opt!=0) free(lgfld->list_opt);
          jerr=g2_unpack3(cgrib,&iofst,&igds,&lgfld->igdtmpl,
                          &lgfld->igdtlen,&lgfld->list_opt,&lgfld->num_opt);
          if (jerr == 0) {
            have3=1;
            lgfld->griddef=igds[0];
            lgfld->ngrdpts=igds[1];
            lgfld->numoct_opt=igds[2];
            lgfld->interp_opt=igds[3];
            lgfld->igdtnum=igds[4];
          }
          else {
            ierr=10;
            return(ierr);
          }
        }
        //
        //   If found Section 4, check to see if this field is the
        //   one requested.
        //
        if (isecnum == 4) {
          numfld=numfld+1;
          if (numfld == ifldnum) {
            lgfld->discipline=disc;
            lgfld->version=ver;
            lgfld->ifldnum=ifldnum;
            lgfld->unpacked=unpack;
            lgfld->expanded=0;
            iofst=iofst-40;       // reset offset to beginning of section
            jerr=g2_unpack4(cgrib,&iofst,&lgfld->ipdtnum,
                            &lgfld->ipdtmpl,&lgfld->ipdtlen,&lgfld->coord_list,
                            &lgfld->num_coord);
            if (jerr == 0)
              have4=1;
            else {
              ierr=11;
              return(ierr);
            }
          }
        }
        //
        //   If found Section 5, check to see if this field is the
        //   one requested.
        //
        if (isecnum == 5 && numfld == ifldnum) {
          iofst=iofst-40;       // reset offset to beginning of section
          jerr=g2_unpack5(cgrib,&iofst,&lgfld->ndpts,&lgfld->idrtnum,
                          &lgfld->idrtmpl,&lgfld->idrtlen);
          if (jerr == 0)
            have5=1;
          else {
            ierr=12;
            return(ierr);
          }
        }
        //
        //   If found Section 6, Unpack bitmap.
        //   Save in case this is the latest
        //   bitmap before the requested field.
        //
        if (isecnum == 6) {
          if (unpack) {   // unpack bitmap
            iofst=iofst-40;           // reset offset to beginning of section
            bmpsave=lgfld->bmap;      // save pointer to previous bitmap
            jerr=g2_unpack6(cgrib,&iofst,lgfld->ngrdpts,&lgfld->ibmap,
                         &lgfld->bmap);
            if (jerr == 0) {
              have6=1;
              if (lgfld->ibmap == 254)     // use previously specified bitmap
                 if( bmpsave!=0 ) 
                    lgfld->bmap=bmpsave;
                 else {
                    printf("g2_getfld: Prev bit-map specified, but none exist.\n");
                    ierr=17;
                    return(ierr);
                 }
              else                         // get rid of it
                 if( bmpsave!=0 ) free(bmpsave);
            }
            else {
              ierr=13;
              return(ierr);
            }
          }
          else {    // do not unpack bitmap
            gbit(cgrib,&lgfld->ibmap,iofst,8);      // Get BitMap Indicator
            have6=1;
          }
        }
        //
        //   If found Section 7, check to see if this field is the
        //   one requested.
        //
        if (isecnum==7 && numfld==ifldnum && unpack) {
          iofst=iofst-40;       // reset offset to beginning of section
          jerr=g2_unpack7(cgrib,&iofst,lgfld->igdtnum,lgfld->igdtmpl,
                          lgfld->idrtnum,lgfld->idrtmpl,lgfld->ndpts,
                          &lgfld->fld);
          if (jerr == 0) {
            have7=1;
            //  If bitmap is used with this field, expand data field 
            //  to grid, if possible.
            if ( lgfld->ibmap != 255 && lgfld->bmap != 0 ) {
               if ( expand == 1 ) {
                  n=0;
                  newfld=(g2float *)calloc(lgfld->ngrdpts,sizeof(g2float));
                  for (j=0;j<lgfld->ngrdpts;j++) {
                      if (lgfld->bmap[j]==1) newfld[j]=lgfld->fld[n++];
                  }
                  free(lgfld->fld);
                  lgfld->fld=newfld;
                  lgfld->expanded=1;
               }
               else {
                  lgfld->expanded=0;
               }
            }
            else {
               lgfld->expanded=1;
            }
          }
          else {
            printf("g2_getfld: return from g2_unpack7 = %d \n",(int)jerr);
            ierr=14;
            return(ierr);
          }
        }
        //
        //   Check to see if we read pass the end of the GRIB
        //   message and missed the terminator string '7777'.
        //
        ipos=ipos+lensec;                // Update beginning of section pointer
        if (ipos > (istart+lengrib)) {
          printf("g2_getfld: '7777'  not found at end of GRIB message.\n");
          ierr=7;
          return(ierr);
        }
        //
        //  If unpacking requested, return when all sections have been
        //  processed
        //
        if (unpack && have3 && have4 && have5 && have6 && have7)
            return(ierr);
        //
        //  If unpacking is not requested, return when sections 
        //  3 through 6 have been processed
        //
        if ((! unpack) && have3 && have4 && have5 && have6)
            return(ierr);
        
      }

//
//  If exited from above loop, the end of the GRIB message was reached
//  before the requested field was found.
//
      printf("g2_getfld: GRIB message contained %d different fields.\n",numfld);
      printf("g2_getfld: The request was for field %d.\n",ifldnum);
      ierr=6;

      return(ierr);

}
Exemplo n.º 17
0
g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen)
/*//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack1 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-29
//
// ABSTRACT: This subroutine unpacks Section 1 (Identification Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-29  Gilbert
//
// USAGE:    int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,
//                          g2int *idslen)
//   INPUT ARGUMENTS:
//     cgrib    - char array containing Section 1 of the GRIB2 message
//     iofst    - Bit offset for the beginning of Section 1 in cgrib.
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset at the end of Section 1, returned.
//     ids      - address of pointer to integer array containing information 
//                read from Section 1, the Identification section.
//            ids[0]  = Identification of originating Centre
//                                 ( see Common Code Table C-1 )
//            ids[1]  = Identification of originating Sub-centre
//            ids[2]  = GRIB Master Tables Version Number
//                                 ( see Code Table 1.0 )
//            ids[3]  = GRIB Local Tables Version Number
//                                 ( see Code Table 1.1 )
//            ids[4]  = Significance of Reference Time (Code Table 1.2)
//            ids[5]  = Year ( 4 digits )
//            ids[6]  = Month
//            ids[7]  = Day
//            ids[8]  = Hour
//            ids[9]  = Minute
//            ids[10]  = Second
//            ids[11]  = Production status of processed data
//                                 ( see Code Table 1.3 )
//            ids[12]  = Type of processed data ( see Code Table 1.4 )
//     idslen   - Number of elements in ids[].
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Array passed is not section 1
//                6 = memory allocation error
//
// REMARKS: 
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$
*/
{

      g2int i,lensec,nbits,ierr,isecnum;
      g2int mapid[13]={2,2,1,1,1,2,1,1,1,1,1,1,1};

      ierr=0;
      *idslen=13;
      *ids=0;

      gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
      *iofst=*iofst+32;
      gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
      *iofst=*iofst+8;

      if ( isecnum != 1 ) {
         ierr=2;
         *idslen=13;
         // fprintf(stderr,"g2_unpack1: Not Section 1 data.\n");
         return(ierr);
      }

      //
      //   Unpack each value into array ids from the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapid.
      //
      *ids=(g2int *)calloc(*idslen,sizeof(g2int));
      if (*ids == 0) {
         ierr=6;
         return(ierr);
      }
      
      for (i=0;i<*idslen;i++) {
        nbits=mapid[i]*8;
        gbit(cgrib,*ids+i,*iofst,nbits);
        *iofst=*iofst+nbits;
      }
      
      return(ierr);    // End of Section 1 processing
}
Exemplo n.º 18
0
g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_addlocal
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
//
// ABSTRACT: This routine adds a Local Use Section (Section 2) to
//   a GRIB2 message.  It is used with routines "g2_create",
//   "g2_addgrid", "g2_addfield",
//   and "g2_gribend" to create a complete GRIB2 message.
//   g2_create must be called first to initialize a new GRIB2 message.
//
// PROGRAM HISTORY LOG:
// 2002-11-01  Gilbert
//
// USAGE:    int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,
//                           g2int lcsec2)
//   INPUT ARGUMENTS:
//     cgrib    - Char array that contains the GRIB2 message to which section
//                2 should be added.
//     csec2    - Character array containing information to be added in
//                Section 2.
//     lcsec2   - Number of bytes of character array csec2 to be added to
//                Section 2.
//
//   OUTPUT ARGUMENT:
//     cgrib    - Char array to contain the updated GRIB2 message.
//                Must be allocated large enough to store the entire
//                GRIB2 message.
//
//   RETURN VALUES:
//     ierr     - Return code.
//              > 0 = Current size of updated GRIB2 message
//               -1 = GRIB message was not initialized.  Need to call
//                    routine gribcreate first.
//               -2 = GRIB message already complete.  Cannot add new section.
//               -3 = Sum of Section byte counts doesn't add to total byte count
//               -4 = Previous Section was not 1 or 7.
//
// REMARKS: Note that the Local Use Section ( Section 2 ) can only follow
//          Section 1 or Section 7 in a GRIB2 message.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$
{

      const unsigned char G=0x47;       // 'G'
      const unsigned char R=0x52;       // 'R'
      const unsigned char I=0x49;       // 'I'
      const unsigned char B=0x42;       // 'B'
      const unsigned char seven=0x37;   // '7'

      const g2int two=2;
      g2int   j,k,lensec2,iofst,ibeg,lencurr,ilen,len,istart;
      g2int   isecnum;

//
//  Check to see if beginning of GRIB message exists
//
      if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
        printf("g2_addlocal: GRIB not found in given message.\n");
        printf("g2_addlocal: Call to routine g2_create required to initialize GRIB message.\n");
        return(-1);
      }
//
//  Get current length of GRIB message
//
      gbit(cgrib,&lencurr,96,32);
//
//  Check to see if GRIB message is already complete
//
      if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
           cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
        printf("g2_addlocal: GRIB message already complete.  Cannot add new section.\n");
        return(-2);
      }
//
//  Loop through all current sections of the GRIB message to
//  find the last section number.
//
      len=16;    // length of Section 0
      for (;;) {
      //    Get section number and length of next section
        iofst=len*8;
        gbit(cgrib,&ilen,iofst,32);
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);
        len=len+ilen;
      //    Exit loop if last section reached
        if ( len == lencurr ) break;
      //    If byte count for each section doesn't match current
      //    total length, then there is a problem.
        if ( len > lencurr ) {
          printf("g2_addlocal: Section byte counts don't add to total.\n");
          printf("g2_addlocal: Sum of section byte counts = %d\n",len);
          printf("g2_addlocal: Total byte count in Section 0 = %d\n",lencurr);
          return(-3);
        }
      }
//
//  Section 2 can only be added after sections 1 and 7.
//
      if ( (isecnum!=1) && (isecnum!=7) ) {
        printf("g2_addlocal: Section 2 can only be added after Section 1 or Section 7.\n");
        printf("g2_addlocal: Section %d was the last found in given GRIB message.\n",isecnum);
        return(-4);
      }
//
//  Add Section 2  - Local Use Section
//
      ibeg=lencurr*8;        //   Calculate offset for beginning of section 2
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&two,iofst,8);     // Store section number ( 2 )
      istart=lencurr+5;
      //cgrib(istart+1:istart+lcsec2)=csec2(1:lcsec2)
      k=0;
      for (j=istart;j<istart+lcsec2;j++) {
         cgrib[j]=csec2[k++];
      }
      //
      //   Calculate length of section 2 and store it in octets
      //   1-4 of section 2.
      //
      lensec2=lcsec2+5;      // bytes
      sbit(cgrib,&lensec2,ibeg,32);

//
//  Update current byte total of message in Section 0
//
      lencurr+=lensec2;
      sbit(cgrib,&lencurr,96,32);

      return(lencurr);

}
Exemplo n.º 19
0
g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
                g2float *coordlist,g2int numcoord,g2int idrsnum,g2int *idrstmpl,
                g2float *fld,g2int ngrdpts,g2int ibmap,g2int *bmap)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_addfield 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-05
//
// ABSTRACT: This routine packs up Sections 4 through 7 for a given field
//   and adds them to a GRIB2 message.  They are Product Definition Section,
//   Data Representation Section, Bit-Map Section and Data Section, 
//   respectively.
//   This routine is used with routines "g2_create", "g2_addlocal", 
//   "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.  
//   g2_create must be called first to initialize a new GRIB2 message.
//   Also, routine g2_addgrid must be called after g2_create and
//   before this routine to add the appropriate grid description to
//   the GRIB2 message.   Also, a call to g2_gribend is required to complete 
//   GRIB2 message after all fields have been added.
//
// PROGRAM HISTORY LOG:
// 2002-11-05  Gilbert
// 2002-12-23  Gilbert  -  Added complex spherical harmonic packing
// 2003-08-27  Gilbert  - Added support for new templates using
//                        PNG and JPEG2000 algorithms/templates.
// 2004-11-29  Gilbert  - JPEG2000 now allowed to use WMO Template no. 5.40
//                        PNG now allowed to use WMO Template no. 5.41
//                      - Added check to determine if packing algorithm failed.
// 2005-05-10  Gilbert -  Imposed minimum size on cpack, used to hold encoded
//                        bit string.
//
// USAGE:    int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
//              g2float *coordlist,g2int numcoord,g2int idrsnum,g2int *idrstmpl,
//              g2float *fld,g2int ngrdpts,g2int ibmap,g2int *bmap)
//   INPUT ARGUMENT LIST:
//     cgrib    - Char array that contains the GRIB2 message to which sections
//                4 through 7 should be added.
//     ipdsnum  - Product Definition Template Number ( see Code Table 4.0)
//     ipdstmpl - Contains the data values for the specified Product Definition
//                Template ( N=ipdsnum ).  Each element of this integer 
//                array contains an entry (in the order specified) of Product
//                Defintion Template 4.N
//     coordlist- Array containg floating point values intended to document
//                the vertical discretisation associated to model data
//                on hybrid coordinate vertical levels.
//     numcoord - number of values in array coordlist.
//     idrsnum  - Data Representation Template Number ( see Code Table 5.0 )
//     idrstmpl - Contains the data values for the specified Data Representation
//                Template ( N=idrsnum ).  Each element of this integer 
//                array contains an entry (in the order specified) of Data
//                Representation Template 5.N
//                Note that some values in this template (eg. reference
//                values, number of bits, etc...) may be changed by the
//                data packing algorithms.
//                Use this to specify scaling factors and order of
//                spatial differencing, if desired.
//     fld[]    - Array of data points to pack.
//     ngrdpts  - Number of data points in grid.
//                i.e.  size of fld and bmap.
//     ibmap    - Bitmap indicator ( see Code Table 6.0 )
//                0 = bitmap applies and is included in Section 6.
//                1-253 = Predefined bitmap applies
//                254 = Previously defined bitmap applies to this field
//                255 = Bit map does not apply to this product.
//     bmap[]   - Integer array containing bitmap to be added. ( if ibmap=0 )
//
//   OUTPUT ARGUMENT LIST:      
//     cgrib    - Character array to contain the updated GRIB2 message.
//                Must be allocated large enough to store the entire
//                GRIB2 message.
//
//   RETURN VALUES:
//     ierr     - Return code.
//              > 0 = Current size of updated GRIB2 message
//               -1 = GRIB message was not initialized.  Need to call
//                    routine g2_create first.
//               -2 = GRIB message already complete.  Cannot add new section.
//               -3 = Sum of Section byte counts doesn't add to total byte count
//               -4 = Previous Section was not 3 or 7.
//               -5 = Could not find requested Product Definition Template.
//               -6 = Section 3 (GDS) not previously defined in message
//               -7 = Tried to use unsupported Data Representationi Template
//               -8 = Specified use of a previously defined bitmap, but one
//                    does not exist in the GRIB message.
//               -9 = GDT of one of 5.50 through 5.53 required to pack field
//                    using DRT 5.51.
//              -10 = Error packing data field.
//
// REMARKS: Note that the Sections 4 through 7 can only follow
//          Section 3 or Section 7 in a GRIB2 message.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$
{
      g2int ierr;
      static unsigned char G=0x47;       // 'G'
      static unsigned char R=0x52;       // 'R'
      static unsigned char I=0x49;       // 'I'
      static unsigned char B=0x42;       // 'B'
      static unsigned char s7=0x37;   // '7'

      unsigned char *cpack;
      static g2int  zero=0,one=1,four=4,five=5,six=6,seven=7;
      const g2int  minsize=50000;
      g2int   iofst,ibeg,lencurr,len,nsize;
      g2int   ilen,isecnum,i,nbits,temp,left;
      g2int   ibmprev,j,lcpack,ioctet,newlen,ndpts;
      g2int   lensec4,lensec5,lensec6,lensec7;
      g2int   issec3,isprevbmap,lpos3=0,JJ,KK,MM;
      g2int   *coordieee;
      g2int   width,height,iscan,itemp;
      g2float *pfld;
      xxtemplate  *mappds,*mapdrs;
      unsigned int allones=4294967295u;
 
      ierr=0;
//
//  Check to see if beginning of GRIB message exists
//
      if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
        printf("g2_addfield: GRIB not found in given message.\n");
        printf("g2_addfield: Call to routine g2_create required to initialize GRIB messge.\n");
        ierr=-1;
        return(ierr);
      }
//
//  Get current length of GRIB message
//  
      gbit(cgrib,&lencurr,96,32);
//
//  Check to see if GRIB message is already complete
//  
      if ( cgrib[lencurr-4]==s7 && cgrib[lencurr-3]==s7 &&
           cgrib[lencurr-2]==s7 && cgrib[lencurr-1]==s7 ) {
        printf("g2_addfield: GRIB message already complete.  Cannot add new section.\n");
        ierr=-2;
        return(ierr);
      }
//
//  Loop through all current sections of the GRIB message to
//  find the last section number.
//
      issec3=0;
      isprevbmap=0;
      len=16;    // length of Section 0
      for (;;) { 
      //    Get number and length of next section
        iofst=len*8;
        gbit(cgrib,&ilen,iofst,32);
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);
        iofst=iofst+8;
      //  Check if previous Section 3 exists
        if (isecnum == 3) {
            issec3=1;
            lpos3=len;
        }
      //  Check if a previous defined bitmap exists
        if (isecnum == 6) {
          gbit(cgrib,&ibmprev,iofst,8);
          iofst=iofst+8;
          if ((ibmprev >= 0) && (ibmprev <= 253)) isprevbmap=1;
        }
        len=len+ilen;
      //    Exit loop if last section reached
        if ( len == lencurr ) break;
      //    If byte count for each section doesn't match current
      //    total length, then there is a problem.
        if ( len > lencurr ) {
          printf("g2_addfield: Section byte counts don''t add to total.\n");
          printf("g2_addfield: Sum of section byte counts = %d\n",len);
          printf("g2_addfield: Total byte count in Section 0 = %d\n",lencurr);
          ierr=-3;
          return(ierr);
        }
      }
//
//  Sections 4 through 7 can only be added after section 3 or 7.
//
      if ( (isecnum != 3) && (isecnum != 7) ) {
        printf("g2_addfield: Sections 4-7 can only be added after Section 3 or 7.\n");
        printf("g2_addfield: Section ',isecnum,' was the last found in given GRIB message.\n");
        ierr=-4;
        return(ierr);
//
//  Sections 4 through 7 can only be added if section 3 was previously defined.
//
      }
      else if ( ! issec3) {
        printf("g2_addfield: Sections 4-7 can only be added if Section 3 was previously included.\n");
        printf("g2_addfield: Section 3 was not found in given GRIB message.\n");
        printf("g2_addfield: Call to routine addgrid required to specify Grid definition.\n");
        ierr=-6;
        return(ierr);
      }
//
//  Add Section 4  - Product Definition Section
//
      ibeg=lencurr*8;        //   Calculate offset for beginning of section 4
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&four,iofst,8);     // Store section number ( 4 )
      iofst=iofst+8;
      sbit(cgrib,&numcoord,iofst,16);   // Store num of coordinate values
      iofst=iofst+16;
      sbit(cgrib,&ipdsnum,iofst,16);    // Store Prod Def Template num.
      iofst=iofst+16;
      //
      //   Get Product Definition Template
      //
      mappds=getpdstemplate(ipdsnum);
      if (mappds == 0) {          // undefined template
        ierr=-5;
        return(ierr);
      }
      //
      //   Extend the Product Definition Template, if necessary.
      //   The number of values in a specific template may vary
      //   depending on data specified in the "static" part of the
      //   template.
      //
      if ( mappds->needext ) {
        free(mappds);
        mappds=extpdstemplate(ipdsnum,ipdstmpl);
      }
      //
      //   Pack up each input value in array ipdstmpl into the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mappds.
      //
      for (i=0;i<mappds->maplen;i++) {
        nbits=abs(mappds->map[i])*8;
        if ( (mappds->map[i] >= 0) || (ipdstmpl[i] >= 0) )
          sbit(cgrib,ipdstmpl+i,iofst,nbits);
        else {
          sbit(cgrib,&one,iofst,1);
          temp=abs(ipdstmpl[i]);
          sbit(cgrib,&temp,iofst+1,nbits-1);
        }
        iofst=iofst+nbits;
      }
      //  Pack template extension, if appropriate
      j=mappds->maplen;
      if ( mappds->needext && (mappds->extlen > 0) ) {
         for (i=0;i<mappds->extlen;i++) {
           nbits=abs(mappds->ext[i])*8;
           if ( (mappds->ext[i] >= 0) || (ipdstmpl[j] >= 0) )
             sbit(cgrib,ipdstmpl+j,iofst,nbits);
           else {
             sbit(cgrib,&one,iofst,1);
             temp=abs(ipdstmpl[j]);
             sbit(cgrib,&temp,iofst+1,nbits-1);
           }
           iofst=iofst+nbits;
           j++;
         }
      }
      free(mappds);
      //
      //   Add Optional list of vertical coordinate values
      //   after the Product Definition Template, if necessary.
      //
      if ( numcoord != 0 ) {
        coordieee=(g2int *)calloc(numcoord,sizeof(g2int));
        mkieee(coordlist,coordieee,numcoord);
        sbits(cgrib,coordieee,iofst,32,0,numcoord);
        iofst=iofst+(32*numcoord);
        free(coordieee);
      }
      //
      //   Calculate length of section 4 and store it in octets
      //   1-4 of section 4.
      //
      lensec4=(iofst-ibeg)/8;
      sbit(cgrib,&lensec4,ibeg,32);
//
//  Pack Data using appropriate algorithm
//
      //
      //   Get Data Representation Template
      //
      mapdrs=getdrstemplate(idrsnum);
      if (mapdrs == 0) {
        ierr=-5;
        return(ierr);
      }
      //
      //  contract data field, removing data at invalid grid points,
      //  if bit-map is provided with field.
      //
      if ( ibmap == 0 || ibmap==254 ) {
         pfld=(g2float *)malloc(ngrdpts*sizeof(g2float));
         ndpts=0;
         for (j=0;j<ngrdpts;j++) {
             if ( bmap[j]==1 ) pfld[ndpts++]=fld[j];
         }
      }
      else {
         ndpts=ngrdpts;
         pfld=fld;
      }
      nsize=ndpts*4;
      if ( nsize < minsize ) nsize=minsize;
      cpack=malloc(nsize);
      if (idrsnum == 0)           //  Simple Packing
        simpack(pfld,ndpts,idrstmpl,cpack,&lcpack);
      else if (idrsnum==2 || idrsnum==3)           //  Complex Packing
        cmplxpack(pfld,ndpts,idrsnum,idrstmpl,cpack,&lcpack);
      else if (idrsnum == 50) {         //  Sperical Harmonic Simple Packing 
        simpack(pfld+1,ndpts-1,idrstmpl,cpack,&lcpack);
        mkieee(pfld+0,idrstmpl+4,1);  // ensure RE(0,0) value is IEEE format
      }
      else if (idrsnum == 51) {         //  Sperical Harmonic Complex Packing 
        getpoly(cgrib+lpos3,&JJ,&KK,&MM);
        if ( JJ!=0 && KK!=0 && MM!=0 )
           specpack(pfld,ndpts,JJ,KK,MM,idrstmpl,cpack,&lcpack);
        else {
           printf("g2_addfield: Cannot pack DRT 5.51.\n");
           return (-9);
        }
      }
      else if (idrsnum == 40 || idrsnum == 40000) {    /*  JPEG2000 encoding  */
        if (ibmap == 255) {
           getdim(cgrib+lpos3,&width,&height,&iscan);
           if ( width==0 || height==0 ) {
              width=ndpts;
              height=1;
           }
           else if ( width==allones || height==allones ) {
              width=ndpts;
              height=1;
           }
           else if ( (iscan&32) == 32) {   /* Scanning mode: bit 3  */
              itemp=width;
              width=height;
              height=itemp;
           }
        }
        else {
           width=ndpts;
           height=1;
        }
        lcpack=nsize;
        jpcpack(pfld,width,height,idrstmpl,cpack,&lcpack);
      }
#ifdef USE_PNG
      else if (idrsnum == 41 || idrsnum == 40010) {      /*  PNG encoding   */
        if (ibmap == 255) {
           getdim(cgrib+lpos3,&width,&height,&iscan);
           if ( width==0 || height==0 ) {
              width=ndpts;
              height=1;
           }
           else if ( width==allones || height==allones ) {
              width=ndpts;
              height=1;
           }
           else if ( (iscan&32) == 32) {   /* Scanning mode: bit 3  */
              itemp=width;
              width=height;
              height=itemp;
           }
        }
        else {
           width=ndpts;
           height=1;
        }
        pngpack(pfld,width,height,idrstmpl,cpack,&lcpack);
      }
#endif  /* USE_PNG */
      else {
        printf("g2_addfield: Data Representation Template 5.%d not yet implemented.\n",idrsnum);
        ierr=-7;
        return(ierr);
      }
      if ( ibmap == 0 || ibmap==254 ) {      // free temp space
         if (fld != pfld) free(pfld);
      }
      if ( lcpack < 0 ) {
        if( cpack != 0 ) free(cpack);
        ierr=-10;
        return(ierr);
      }

//
//  Add Section 5  - Data Representation Section
//
      ibeg=iofst;            //   Calculate offset for beginning of section 5
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&five,iofst,8);     // Store section number ( 5 )
      iofst=iofst+8;
      sbit(cgrib,&ndpts,iofst,32);    // Store num of actual data points
      iofst=iofst+32;
      sbit(cgrib,&idrsnum,iofst,16);    // Store Data Repr. Template num.
      iofst=iofst+16;
      //
      //   Pack up each input value in array idrstmpl into the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapdrs.
      //
      for (i=0;i<mapdrs->maplen;i++) {
        nbits=abs(mapdrs->map[i])*8;
        if ( (mapdrs->map[i] >= 0) || (idrstmpl[i] >= 0) )
          sbit(cgrib,idrstmpl+i,iofst,nbits);
        else {
          sbit(cgrib,&one,iofst,1);
          temp=abs(idrstmpl[i]);
          sbit(cgrib,&temp,iofst+1,nbits-1);
        }
        iofst=iofst+nbits;
      }
      free(mapdrs);
      //
      //   Calculate length of section 5 and store it in octets
      //   1-4 of section 5.
      //
      lensec5=(iofst-ibeg)/8;
      sbit(cgrib,&lensec5,ibeg,32);

//
//  Add Section 6  - Bit-Map Section
//
      ibeg=iofst;            //   Calculate offset for beginning of section 6
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&six,iofst,8);     // Store section number ( 6 )
      iofst=iofst+8;
      sbit(cgrib,&ibmap,iofst,8);    // Store Bit Map indicator
      iofst=iofst+8;
      //
      //  Store bitmap, if supplied
      //
      if (ibmap == 0) {
        sbits(cgrib,bmap,iofst,1,0,ngrdpts);    // Store BitMap
        iofst=iofst+ngrdpts;
      }
      //
      //  If specifying a previously defined bit-map, make sure
      //  one already exists in the current GRIB message.
      //
      if ((ibmap==254) && ( ! isprevbmap)) {
        printf("g2_addfield: Requested previously defined bitmap,");
        printf(" but one does not exist in the current GRIB message.\n");
        ierr=-8;
        return(ierr);
      }
      //
      //   Calculate length of section 6 and store it in octets
      //   1-4 of section 6.  Pad to end of octect, if necessary.
      //
      left=8-(iofst%8);
      if (left != 8) {
        sbit(cgrib,&zero,iofst,left);     // Pad with zeros to fill Octet
        iofst=iofst+left;
      }
      lensec6=(iofst-ibeg)/8;
      sbit(cgrib,&lensec6,ibeg,32);

//
//  Add Section 7  - Data Section
//
      ibeg=iofst;            //   Calculate offset for beginning of section 7
      iofst=ibeg+32;        //   leave space for length of section
      sbit(cgrib,&seven,iofst,8);    // Store section number ( 7 )
      iofst=iofst+8;
      //      Store Packed Binary Data values, if non-constant field
      if (lcpack != 0) {
        ioctet=iofst/8;
        //cgrib(ioctet+1:ioctet+lcpack)=cpack(1:lcpack)
        for (j=0;j<lcpack;j++) cgrib[ioctet+j]=cpack[j];
        iofst=iofst+(8*lcpack);
      }
      //
      //   Calculate length of section 7 and store it in octets
      //   1-4 of section 7.  
      //
      lensec7=(iofst-ibeg)/8;
      sbit(cgrib,&lensec7,ibeg,32);

      if( cpack != 0 ) free(cpack);
//
//  Update current byte total of message in Section 0
//
      newlen=lencurr+lensec4+lensec5+lensec6+lensec7;
      sbit(cgrib,&newlen,96,32);

      return(newlen);

}
Exemplo n.º 20
0
g2int g2_gribend(unsigned char *cgrib)
//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_gribend 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This routine finalizes a GRIB2 message after all grids
//   and fields have been added.  It adds the End Section ( "7777" )
//   to the end of the GRIB message and calculates the length and stores
//   it in the appropriate place in Section 0.
//   This routine is used with routines "g2_create", "g2_addlocal", 
//   "g2_addgrid", and "g2_addfield" to create a complete GRIB2 message.
//   g2_create must be called first to initialize a new GRIB2 message.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
//
// USAGE:    int g2_gribend(unsigned char *cgrib)
//   INPUT ARGUMENT:
//     cgrib    - Char array containing all the data sections added
//                be previous calls to g2_create, g2_addlocal, g2_addgrid,
//                and g2_addfield.
//
//   OUTPUT ARGUMENTS:      
//     cgrib    - Char array containing the finalized GRIB2 message
//
//   RETURN VALUES:
//     ierr     - Return code.
//              > 0 = Length of the final GRIB2 message in bytes.
//               -1 = GRIB message was not initialized.  Need to call
//                    routine g2_create first.
//               -2 = GRIB message already complete.  
//               -3 = Sum of Section byte counts doesn't add to total byte count
//               -4 = Previous Section was not 7.
//
// REMARKS: This routine is intended for use with routines "g2_create", 
//          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete 
//          GRIB2 message.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:
//
//$$$
{

      g2int iofst,lencurr,len,ilen,isecnum;
      g2int   ierr,lengrib;
      static unsigned char G=0x47;       // 'G'
      static unsigned char R=0x52;       // 'R'
      static unsigned char I=0x49;       // 'I'
      static unsigned char B=0x42;       // 'B'
      static unsigned char seven=0x37;   // '7'
 
      ierr=0;
//
//  Check to see if beginning of GRIB message exists
//
      if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
        printf("g2_gribend: GRIB not found in given message.\n");
        ierr=-1;
        return (ierr);
      }
//
//  Get current length of GRIB message
//  
      gbit(cgrib,&lencurr,96,32);
//
//  Loop through all current sections of the GRIB message to
//  find the last section number.
//
      len=16;    // Length of Section 0
      for (;;) { 
      //    Get number and length of next section
        iofst=len*8;
        gbit(cgrib,&ilen,iofst,32);
        iofst=iofst+32;
        gbit(cgrib,&isecnum,iofst,8);
        len=len+ilen;
      //    Exit loop if last section reached
        if ( len == lencurr ) break;
      //    If byte count for each section doesn't match current
      //    total length, then there is a problem.
        if ( len > lencurr ) {
          printf("g2_gribend: Section byte counts don''t add to total.\n");
          printf("g2_gribend: Sum of section byte counts = %d\n",(int)len);
          printf("g2_gribend: Total byte count in Section 0 = %d\n",(int)lencurr);
          ierr=-3;
          return (ierr);
        }
      }
//
//  Can only add End Section (Section 8) after Section 7.
//
      if ( isecnum != 7 ) {
        printf("g2_gribend: Section 8 can only be added after Section 7.\n");
        printf("g2_gribend: Section %d was the last found in given GRIB message.\n",isecnum);
        ierr=-4;
        return (ierr);
      }
//
//  Add Section 8  - End Section
//
      //cgrib(lencurr+1:lencurr+4)=c7777
      cgrib[lencurr]=seven;
      cgrib[lencurr+1]=seven;
      cgrib[lencurr+2]=seven;
      cgrib[lencurr+3]=seven;

//
//  Update current byte total of message in Section 0
//
      lengrib=lencurr+4;
      sbit(cgrib,&lengrib,96,32);

      return (lengrib);

}
Exemplo n.º 21
0
g2int g2_unpack5(unsigned char *cgrib,size_t sz,g2int *iofst,g2int *ndpts,
        g2int *idrsnum,g2int **idrstmpl,g2int *mapdrslen)
/*//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_unpack5 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This subroutine unpacks Section 5 (Data Representation Section)
//           as defined in GRIB Edition 2.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
// 2009-01-14  Vuong     Changed structure name template to gtemplate
// 2014-02-25  Steve Emmerson (UCAR/Unidata)   Add length-checking of "cgrib"
//                                             array
//
// USAGE:    int g2_unpack5(unsigned char *cgrib,size_t sz,g2int *iofst,
//                      g2int *ndpts, g2int *idrsnum,g2int **idrstmpl,
//                      g2int *mapdrslen)
//   INPUT ARGUMENTS:
//     cgrib    - char array containing Section 5 of the GRIB2 message
//     sz       - Size of "cgrib" array in bytes
//     iofst    - Bit offset for the beginning of Section 5 in cgrib.
//
//   OUTPUT ARGUMENTS:      
//     iofst    - Bit offset at the end of Section 5, returned.
//     ndpts    - Number of data points unpacked and returned.
//     idrsnum  - Data Representation Template Number ( see Code Table 5.0)
//     idrstmpl - Pointer to an integer array containing the data values for 
//                the specified Data Representation
//                Template ( N=idrsnum ).  Each element of this integer
//                array contains an entry (in the order specified) of Data
//                Representation Template 5.N
//     mapdrslen- Number of elements in idrstmpl[].  i.e. number of entries
//                in Data Representation Template 5.N  ( N=idrsnum ).
//
//   RETURN VALUES:
//     ierr     - Error return code.
//                0 = no error
//                2 = Not Section 5
//                6 = memory allocation error
//                7 = "GRIB" message contains an undefined Data
//                    Representation Template.
//
// REMARKS: None
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$*/
{
      g2int ierr,needext,i,j,nbits,isecnum;
      g2int lensec,isign,newlen;
      g2int *lidrstmpl=0;
      gtemplate *mapdrs;
      size_t bitsz = sz * 8;

      ierr=0;
      *idrstmpl=0;       /*NULL*/

      if (*iofst + 40 > bitsz)
          return 2;
      gbit(cgrib,&lensec,*iofst,32);        /* Get Length of Section*/
      *iofst=*iofst+32;
      gbit(cgrib,&isecnum,*iofst,8);         /* Get Section Number*/
      *iofst=*iofst+8;

      if ( isecnum != 5 ) {
         ierr=2;
         *ndpts=0;
         *mapdrslen=0;
        /* fprintf(stderr,"g2_unpack5: Not Section 5 data.\n");*/
         return(ierr);
      }

      if (*iofst + 48 > bitsz)
          return 2;
      gbit(cgrib,ndpts,*iofst,32);    /* Get num of data points*/
      *iofst=*iofst+32;
      gbit(cgrib,idrsnum,*iofst,16);     /* Get Data Rep Template Num.*/
      *iofst=*iofst+16;

      /*   Gen Data Representation Template*/
      mapdrs=getdrstemplate(*idrsnum);
      if (mapdrs == 0) {
        ierr=7;
        *mapdrslen=0;
        return(ierr);
      }
      *mapdrslen=mapdrs->maplen;
      needext=mapdrs->needext;
      /*
      //   Unpack each value into array ipdstmpl from the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapdrs.
      */
      if (*mapdrslen > 0) lidrstmpl=(g2int *)calloc(*mapdrslen,sizeof(g2int));
      if (lidrstmpl == 0) {
         ierr=6;
         *mapdrslen=0;
         *idrstmpl=0;     /*NULL*/
         if ( mapdrs != 0 ) free(mapdrs);
         return(ierr);
      }
      else {
         *idrstmpl=lidrstmpl;
      }
      for (i=0;i<mapdrs->maplen;i++) {
        nbits=abs(mapdrs->map[i])*8;
        if ( mapdrs->map[i] >= 0 ) {
          if (*iofst + nbits > bitsz) {
            free(mapdrs);
            return 2;
          }
          gbit(cgrib,lidrstmpl+i,*iofst,nbits);
        }
        else {
          if (*iofst + nbits > bitsz) {
            free(mapdrs);
            return 2;
          }
          gbit(cgrib,&isign,*iofst,1);
          gbit(cgrib,lidrstmpl+i,*iofst+1,nbits-1);
          if (isign == 1) lidrstmpl[i]=-1*lidrstmpl[i];
        }
        *iofst=*iofst+nbits;
      }
      /*
      //   Check to see if the Data Representation Template needs to be
      //   extended.
      //   The number of values in a specific gtemplate may vary
      //   depending on data specified in the "static" part of the
      //   gtemplate.
      */
      if ( needext == 1 ) {
        free(mapdrs);
        mapdrs=extdrstemplate(*idrsnum,lidrstmpl);
        newlen=mapdrs->maplen+mapdrs->extlen;
        lidrstmpl=(g2int *)realloc(lidrstmpl,newlen*sizeof(g2int));
        *idrstmpl=lidrstmpl;
        /*   Unpack the rest of the Data Representation Template*/
        j=0;
        for (i=*mapdrslen;i<newlen;i++) {
          nbits=abs(mapdrs->ext[j])*8;
          if ( mapdrs->ext[j] >= 0 ) {
            if (*iofst + nbits > bitsz) {
              free(mapdrs);
              return 2;
            }
            gbit(cgrib,lidrstmpl+i,*iofst,nbits);
          }
          else {
            if (*iofst + nbits > bitsz) {
              free(mapdrs);
              return 2;
            }
            gbit(cgrib,&isign,*iofst,1);
            gbit(cgrib,lidrstmpl+i,*iofst+1,nbits-1);
            if (isign == 1) lidrstmpl[i]=-1*lidrstmpl[i];
          }
          *iofst=*iofst+nbits;
          j++;
        }
        *mapdrslen=newlen;
      }
      if( mapdrs->ext != 0 ) free(mapdrs->ext);
      free(mapdrs);

      return(ierr);    /* End of Section 5 processing*/

}