1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
4 #include "grib2.h"
5
6
g2_unpack4(unsigned char * cgrib,g2int cgrib_length,g2int * iofst,g2int * ipdsnum,g2int ** ipdstmpl,g2int * mappdslen,g2float ** coordlist,g2int * numcoord)7 g2int g2_unpack4(unsigned char *cgrib,g2int cgrib_length,g2int *iofst,g2int *ipdsnum,g2int **ipdstmpl,
8 g2int *mappdslen,g2float **coordlist,g2int *numcoord)
9 ////$$$ SUBPROGRAM DOCUMENTATION BLOCK
10 // . . . .
11 // SUBPROGRAM: g2_unpack4
12 // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-10-31
13 //
14 // ABSTRACT: This subroutine unpacks Section 4 (Product Definition Section)
15 // as defined in GRIB Edition 2.
16 //
17 // PROGRAM HISTORY LOG:
18 // 2002-10-31 Gilbert
19 // 2009-01-14 Vuong Changed structure name template to gtemplate
20 //
21 // USAGE: int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,
22 // g2int **ipdstmpl,g2int *mappdslen,
23 // g2float **coordlist,g2int *numcoord)
24 // INPUT ARGUMENTS:
25 // cgrib - Char array containing Section 4 of the GRIB2 message
26 // iofst - Bit offset of the beginning of Section 4 in cgrib.
27 //
28 // OUTPUT ARGUMENTS:
29 // iofst - Bit offset of the end of Section 4, returned.
30 // ipdsnum - Product Definition Template Number ( see Code Table 4.0)
31 // ipdstmpl - Pointer to integer array containing the data values for
32 // the specified Product Definition
33 // Template ( N=ipdsnum ). Each element of this integer
34 // array contains an entry (in the order specified) of Product
35 // Definition Template 4.N
36 // mappdslen- Number of elements in ipdstmpl[]. i.e. number of entries
37 // in Product Definition Template 4.N ( N=ipdsnum ).
38 // coordlist- Pointer to real array containing floating point values
39 // intended to document
40 // the vertical discretisation associated to model data
41 // on hybrid coordinate vertical levels. (part of Section 4)
42 // numcoord - number of values in array coordlist.
43 //
44 // RETURN VALUES:
45 // ierr - Error return code.
46 // 0 = no error
47 // 2 = Not section 4
48 // 5 = "GRIB" message contains an undefined Product Definition
49 // Template.
50 // 6 = memory allocation error
51 //
52 // REMARKS:
53 //
54 // ATTRIBUTES:
55 // LANGUAGE: C
56 // MACHINE:
57 //
58 //$$$//
59 {
60
61 g2int ierr,needext,i,j,nbits,isecnum;
62 g2int lensec,isign,newlen;
63 g2int *coordieee;
64 g2int *lipdstmpl=0;
65 g2float *lcoordlist;
66 gtemplate *mappds;
67
68 ierr=0;
69 *ipdstmpl=0; // NULL
70 *coordlist=0; // NULL
71
72 gbit2(cgrib,cgrib_length,&lensec,*iofst,32); // Get Length of Section
73 *iofst=*iofst+32;
74 gbit2(cgrib,cgrib_length,&isecnum,*iofst,8); // Get Section Number
75 *iofst=*iofst+8;
76
77 if ( isecnum != 4 ) {
78 ierr=2;
79 *numcoord=0;
80 *mappdslen=0;
81 // fprintf(stderr,"g2_unpack4: Not Section 4 data.\n");
82 return(ierr);
83 }
84
85 gbit2(cgrib,cgrib_length,numcoord,*iofst,16); // Get num of coordinate values
86 *iofst=*iofst+16;
87 gbit2(cgrib,cgrib_length,ipdsnum,*iofst,16); // Get Prod. Def Template num.
88 *iofst=*iofst+16;
89
90 // Get Product Definition Template
91 mappds=getpdstemplate(*ipdsnum);
92 if (mappds == 0) { // undefine template
93 ierr=5;
94 *mappdslen=0;
95 return(ierr);
96 }
97 *mappdslen=mappds->maplen;
98 needext=mappds->needext;
99 //
100 // Unpack each value into array ipdstmpl from the
101 // the appropriate number of octets, which are specified in
102 // corresponding entries in array mappds.
103 //
104 if (*mappdslen > 0) lipdstmpl=(g2int *)calloc(*mappdslen,sizeof(g2int));
105 if (lipdstmpl == 0) {
106 ierr=6;
107 *mappdslen=0;
108 *ipdstmpl=0; //NULL
109 free(mappds);
110 return(ierr);
111 }
112 else {
113 *ipdstmpl=lipdstmpl;
114 }
115 for (i=0;i<mappds->maplen;i++) {
116 nbits=abs(mappds->map[i])*8;
117 if ( mappds->map[i] >= 0 ) {
118 gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits);
119 }
120 else {
121 gbit2(cgrib,cgrib_length,&isign,*iofst,1);
122 gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1);
123 if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
124 }
125 *iofst=*iofst+nbits;
126 }
127 //
128 // Check to see if the Product Definition Template needs to be
129 // extended.
130 // The number of values in a specific template may vary
131 // depending on data specified in the "static" part of the
132 // template.
133 //
134 if ( needext ==1 ) {
135 free(mappds);
136 mappds=extpdstemplate(*ipdsnum,lipdstmpl);
137 newlen=mappds->maplen+mappds->extlen;
138 lipdstmpl=(g2int *)realloc(lipdstmpl,newlen*sizeof(g2int));
139 *ipdstmpl=lipdstmpl;
140 // Unpack the rest of the Product Definition Template
141 j=0;
142 for (i=*mappdslen;i<newlen;i++) {
143 #ifdef notneeded
144 if( mappds->ext[j] < INT_MIN / 8 || mappds->ext[j] > INT_MAX / 8 )
145 {
146 ierr=6;
147 *numcoord=0;
148 *mappdslen=0;
149 *coordlist=0; // NULL
150 *ipdstmpl=0;
151 free(mappds->ext);
152 free(mappds);
153 free(lipdstmpl);
154 return(ierr);
155 }
156 #endif
157 nbits=abs(mappds->ext[j])*8;
158 lipdstmpl[i] = 0;
159 if ( mappds->ext[j] >= 0 ) {
160 gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits);
161 }
162 else {
163 gbit2(cgrib,cgrib_length,&isign,*iofst,1);
164 gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1);
165 if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
166 }
167 *iofst=*iofst+nbits;
168 j++;
169 }
170 *mappdslen=newlen;
171 }
172 free(mappds->ext);
173 free(mappds);
174 //
175 // Get Optional list of vertical coordinate values
176 // after the Product Definition Template, if necessary.
177 //
178 *coordlist=0; // NULL
179 if ( *numcoord != 0 ) {
180 coordieee=(g2int *)calloc(*numcoord,sizeof(g2int));
181 lcoordlist=(g2float *)calloc(*numcoord,sizeof(g2float));
182 if (coordieee == 0 || lcoordlist == 0) {
183 ierr=6;
184 *numcoord=0;
185 *coordlist=0; // NULL
186 if( coordieee != 0 ) free(coordieee);
187 if( lcoordlist != 0 ) free(lcoordlist);
188 return(ierr);
189 }
190 else {
191 *coordlist=lcoordlist;
192 }
193 gbits(cgrib,cgrib_length,coordieee,*iofst,32,0,*numcoord);
194 rdieee(coordieee,*coordlist,*numcoord);
195 free(coordieee);
196 *iofst=*iofst+(32*(*numcoord));
197 }
198
199 return(ierr); // End of Section 4 processing
200
201 }
202