1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include "grib2.h"
4 :
5 :
6 0 : g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflist,g2int idefnum)
7 : //$$$ SUBPROGRAM DOCUMENTATION BLOCK
8 : // . . . .
9 : // SUBPROGRAM: g2_addgrid
10 : // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-01
11 : //
12 : // ABSTRACT: This routine packs up a Grid Definition Section (Section 3)
13 : // and adds it to a GRIB2 message. It is used with routines "g2_create",
14 : // "g2_addlocal", "g2_addfield",
15 : // and "g2_gribend" 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-11-01 Gilbert
20 : //
21 : // USAGE: int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,
22 : // g2int *ideflist,g2int idefnum)
23 : // INPUT ARGUMENTS:
24 : // cgrib - Char array that contains the GRIB2 message to which
25 : // section should be added.
26 : // igds - Contains information needed for GRIB Grid Definition Section 3
27 : // Must be dimensioned >= 5.
28 : // igds[0]=Source of grid definition (see Code Table 3.0)
29 : // igds[1]=Number of grid points in the defined grid.
30 : // igds[2]=Number of octets needed for each
31 : // additional grid points definition.
32 : // Used to define number of
33 : // points in each row ( or column ) for
34 : // non-regular grids.
35 : // = 0, if using regular grid.
36 : // igds[3]=Interpretation of list for optional points
37 : // definition. (Code Table 3.11)
38 : // igds[4]=Grid Definition Template Number (Code Table 3.1)
39 : // igdstmpl - Contains the data values for the specified Grid Definition
40 : // Template ( NN=igds[4] ). Each element of this integer
41 : // array contains an entry (in the order specified) of Grid
42 : // Defintion Template 3.NN
43 : // ideflist - (Used if igds[2] != 0) This array contains the
44 : // number of grid points contained in each row ( or column )
45 : // idefnum - (Used if igds[2] != 0) The number of entries
46 : // in array ideflist. i.e. number of rows ( or columns )
47 : // for which optional grid points are defined.
48 : //
49 : // OUTPUT ARGUMENTS:
50 : // cgrib - Char array to contain the updated GRIB2 message.
51 : // Must be allocated large enough to store the entire
52 : // GRIB2 message.
53 : //
54 : // RETURN VALUES:
55 : // ierr - Return code.
56 : // > 0 = Current size of updated GRIB2 message
57 : // -1 = GRIB message was not initialized. Need to call
58 : // routine gribcreate first.
59 : // -2 = GRIB message already complete. Cannot add new section.
60 : // -3 = Sum of Section byte counts doesn't add to total byte count
61 : // -4 = Previous Section was not 1, 2 or 7.
62 : // -5 = Could not find requested Grid Definition Template.
63 : //
64 : // REMARKS: Note that the Grid Def Section ( Section 3 ) can only follow
65 : // Section 1, 2 or Section 7 in a GRIB2 message.
66 : //
67 : // ATTRIBUTES:
68 : // LANGUAGE: C
69 : // MACHINE:
70 : //
71 : //$$$
72 : {
73 :
74 : g2int ierr;
75 : static unsigned char G=0x47; // 'G'
76 : static unsigned char R=0x52; // 'R'
77 : static unsigned char I=0x49; // 'I'
78 : static unsigned char B=0x42; // 'B'
79 : static unsigned char seven=0x37; // '7'
80 :
81 : static g2int one=1,three=3,miss=65535;
82 : g2int lensec3,iofst,ibeg,lencurr,len;
83 : g2int i,j,temp,ilen,isecnum,nbits;
84 0 : xxtemplate *mapgrid=0;
85 :
86 0 : ierr=0;
87 : //
88 : // Check to see if beginning of GRIB message exists
89 : //
90 0 : if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
91 0 : printf("g2_addgrid: GRIB not found in given message.\n");
92 0 : printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB messge.\n");
93 0 : ierr=-1;
94 0 : return(ierr);
95 : }
96 : //
97 : // Get current length of GRIB message
98 : //
99 0 : gbit(cgrib,&lencurr,96,32);
100 : //
101 : // Check to see if GRIB message is already complete
102 : //
103 0 : if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
104 0 : cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
105 0 : printf("g2_addgrid: GRIB message already complete. Cannot add new section.\n");
106 0 : ierr=-2;
107 0 : return(ierr);
108 : }
109 : //
110 : // Loop through all current sections of the GRIB message to
111 : // find the last section number.
112 : //
113 0 : len=16; // length of Section 0
114 : for (;;) {
115 : // Get section number and length of next section
116 0 : iofst=len*8;
117 0 : gbit(cgrib,&ilen,iofst,32);
118 0 : iofst=iofst+32;
119 0 : gbit(cgrib,&isecnum,iofst,8);
120 0 : len=len+ilen;
121 : // Exit loop if last section reached
122 0 : if ( len == lencurr ) break;
123 : // If byte count for each section doesn't match current
124 : // total length, then there is a problem.
125 0 : if ( len > lencurr ) {
126 0 : printf("g2_addgrid: Section byte counts don''t add to total.\n");
127 0 : printf("g2_addgrid: Sum of section byte counts = %d\n",len);
128 0 : printf("g2_addgrid: Total byte count in Section 0 = %d\n",lencurr);
129 0 : ierr=-3;
130 0 : return(ierr);
131 : }
132 0 : }
133 : //
134 : // Section 3 can only be added after sections 1, 2 and 7.
135 : //
136 0 : if ( (isecnum!=1) && (isecnum!=2) && (isecnum!=7) ) {
137 0 : printf("g2_addgrid: Section 3 can only be added after Section 1, 2 or 7.\n");
138 0 : printf("g2_addgrid: Section ',isecnum,' was the last found in given GRIB message.\n");
139 0 : ierr=-4;
140 0 : return(ierr);
141 : }
142 : //
143 : // Add Section 3 - Grid Definition Section
144 : //
145 0 : ibeg=lencurr*8; // Calculate offset for beginning of section 3
146 0 : iofst=ibeg+32; // leave space for length of section
147 0 : sbit(cgrib,&three,iofst,8); // Store section number ( 3 )
148 0 : iofst=iofst+8;
149 0 : sbit(cgrib,igds+0,iofst,8); // Store source of Grid def.
150 0 : iofst=iofst+8;
151 0 : sbit(cgrib,igds+1,iofst,32); // Store number of data pts.
152 0 : iofst=iofst+32;
153 0 : sbit(cgrib,igds+2,iofst,8); // Store number of extra octets.
154 0 : iofst=iofst+8;
155 0 : sbit(cgrib,igds+3,iofst,8); // Store interp. of extra octets.
156 0 : iofst=iofst+8;
157 : // if Octet 6 is not equal to zero, Grid Definition Template may
158 : // not be supplied.
159 0 : if ( igds[0] == 0 )
160 0 : sbit(cgrib,igds+4,iofst,16); // Store Grid Def Template num.
161 : else
162 0 : sbit(cgrib,&miss,iofst,16); // Store missing value as Grid Def Template num.
163 0 : iofst=iofst+16;
164 : //
165 : // Get Grid Definition Template
166 : //
167 0 : if (igds[0] == 0) {
168 0 : mapgrid=getgridtemplate(igds[4]);
169 0 : if (mapgrid == 0) { // undefined template
170 0 : ierr=-5;
171 0 : return(ierr);
172 : }
173 : //
174 : // Extend the Grid Definition Template, if necessary.
175 : // The number of values in a specific template may vary
176 : // depending on data specified in the "static" part of the
177 : // template.
178 : //
179 0 : if ( mapgrid->needext ) {
180 0 : free(mapgrid);
181 0 : mapgrid=extgridtemplate(igds[4],igdstmpl);
182 : }
183 : }
184 : //
185 : // Pack up each input value in array igdstmpl into the
186 : // the appropriate number of octets, which are specified in
187 : // corresponding entries in array mapgrid.
188 : //
189 0 : for (i=0;i<mapgrid->maplen;i++) {
190 0 : nbits=abs(mapgrid->map[i])*8;
191 0 : if ( (mapgrid->map[i] >= 0) || (igdstmpl[i] >= 0) )
192 0 : sbit(cgrib,igdstmpl+i,iofst,nbits);
193 : else {
194 0 : sbit(cgrib,&one,iofst,1);
195 0 : temp=abs(igdstmpl[i]);
196 0 : sbit(cgrib,&temp,iofst+1,nbits-1);
197 : }
198 0 : iofst=iofst+nbits;
199 : }
200 : // Pack template extension, if appropriate
201 0 : j=mapgrid->maplen;
202 0 : if ( mapgrid->needext && (mapgrid->extlen > 0) ) {
203 0 : for (i=0;i<mapgrid->extlen;i++) {
204 0 : nbits=abs(mapgrid->ext[i])*8;
205 0 : if ( (mapgrid->ext[i] >= 0) || (igdstmpl[j] >= 0) )
206 0 : sbit(cgrib,igdstmpl+j,iofst,nbits);
207 : else {
208 0 : sbit(cgrib,&one,iofst,1);
209 0 : temp=abs(igdstmpl[j]);
210 0 : sbit(cgrib,&temp,iofst+1,nbits-1);
211 : }
212 0 : iofst=iofst+nbits;
213 0 : j++;
214 : }
215 : }
216 0 : free(mapgrid);
217 : //
218 : // If requested,
219 : // Insert optional list of numbers defining number of points
220 : // in each row or column. This is used for non regular
221 : // grids.
222 : //
223 0 : if ( igds[2] != 0 ) {
224 0 : nbits=igds[2]*8;
225 0 : sbits(cgrib,ideflist,iofst,nbits,0,idefnum);
226 0 : iofst=iofst+(nbits*idefnum);
227 : }
228 : //
229 : // Calculate length of section 3 and store it in octets
230 : // 1-4 of section 3.
231 : //
232 0 : lensec3=(iofst-ibeg)/8;
233 0 : sbit(cgrib,&lensec3,ibeg,32);
234 :
235 : //
236 : // Update current byte total of message in Section 0
237 : //
238 0 : lencurr+=lensec3;
239 0 : sbit(cgrib,&lencurr,96,32);
240 :
241 0 : return(lencurr);
242 :
243 : }
|