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); }
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 }