1 #include <stdio.h>
2 #include "grib2.h"
3 
g2_gribend(unsigned char * cgrib)4 g2int g2_gribend(unsigned char *cgrib)
5 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
6 //                .      .    .                                       .
7 // SUBPROGRAM:    g2_gribend
8 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
9 //
10 // ABSTRACT: This routine finalizes a GRIB2 message after all grids
11 //   and fields have been added.  It adds the End Section ( "7777" )
12 //   to the end of the GRIB message and calculates the length and stores
13 //   it in the appropriate place in Section 0.
14 //   This routine is used with routines "g2_create", "g2_addlocal",
15 //   "g2_addgrid", and "g2_addfield" to create a complete GRIB2 message.
16 //   g2_create must be called first to initialize a new GRIB2 message.
17 //
18 // PROGRAM HISTORY LOG:
19 // 2002-10-31  Gilbert
20 //
21 // USAGE:    int g2_gribend(unsigned char *cgrib)
22 //   INPUT ARGUMENT:
23 //     cgrib    - Char array containing all the data sections added
24 //                be previous calls to g2_create, g2_addlocal, g2_addgrid,
25 //                and g2_addfield.
26 //
27 //   OUTPUT ARGUMENTS:
28 //     cgrib    - Char array containing the finalized GRIB2 message
29 //
30 //   RETURN VALUES:
31 //     ierr     - Return code.
32 //              > 0 = Length of the final GRIB2 message in bytes.
33 //               -1 = GRIB message was not initialized.  Need to call
34 //                    routine g2_create first.
35 //               -2 = GRIB message already complete.
36 //               -3 = Sum of Section byte counts doesn't add to total byte count
37 //               -4 = Previous Section was not 7.
38 //
39 // REMARKS: This routine is intended for use with routines "g2_create",
40 //          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete
41 //          GRIB2 message.
42 //
43 // ATTRIBUTES:
44 //   LANGUAGE: C
45 //   MACHINE:
46 //
47 //$$$
48 {
49 
50       g2int iofst,lencurr,len,ilen,isecnum;
51       g2int   ierr,lengrib;
52       const unsigned char G=0x47;       // 'G'
53       const unsigned char R=0x52;       // 'R'
54       const unsigned char I=0x49;       // 'I'
55       const unsigned char B=0x42;       // 'B'
56       const unsigned char seven=0x37;   // '7'
57 
58 //
59 //  Check to see if beginning of GRIB message exists
60 //
61       if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
62         printf("g2_gribend: GRIB not found in given message.\n");
63         ierr=-1;
64         return (ierr);
65       }
66 //
67 //  Get current length of GRIB message
68 //
69       gbit(cgrib,&lencurr,96,32);
70 //
71 //  Loop through all current sections of the GRIB message to
72 //  find the last section number.
73 //
74       len=16;    // Length of Section 0
75       for (;;) {
76       //    Get number and length of next section
77         iofst=len*8;
78         gbit(cgrib,&ilen,iofst,32);
79         iofst=iofst+32;
80         gbit(cgrib,&isecnum,iofst,8);
81         len=len+ilen;
82       //    Exit loop if last section reached
83         if ( len == lencurr ) break;
84       //    If byte count for each section doesn't match current
85       //    total length, then there is a problem.
86         if ( len > lencurr ) {
87           printf("g2_gribend: Section byte counts don''t add to total.\n");
88           printf("g2_gribend: Sum of section byte counts = %d\n",(int)len);
89           printf("g2_gribend: Total byte count in Section 0 = %d\n",(int)lencurr);
90           ierr=-3;
91           return (ierr);
92         }
93       }
94 //
95 //  Can only add End Section (Section 8) after Section 7.
96 //
97       if ( isecnum != 7 ) {
98         printf("g2_gribend: Section 8 can only be added after Section 7.\n");
99         printf("g2_gribend: Section %d was the last found in given GRIB message.\n",isecnum);
100         ierr=-4;
101         return (ierr);
102       }
103 //
104 //  Add Section 8  - End Section
105 //
106       //cgrib(lencurr+1:lencurr+4)=c7777
107       cgrib[lencurr]=seven;
108       cgrib[lencurr+1]=seven;
109       cgrib[lencurr+2]=seven;
110       cgrib[lencurr+3]=seven;
111 
112 //
113 //  Update current byte total of message in Section 0
114 //
115       lengrib=lencurr+4;
116       sbit(cgrib,&lengrib,96,32);
117 
118       return (lengrib);
119 
120 }
121 
122