예제 #1
0
파일: g2_addgrid.c 프로젝트: exit130/g2clib
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);

}
예제 #2
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
}