Line data Source code
1 : #include <stdio.h>
2 : #include <stdlib.h>
3 : #include <limits.h>
4 : #include "grib2.h"
5 :
6 :
7 824 : 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 824 : g2int ierr,needext,i,j,nbits,isecnum = 0;
62 824 : g2int lensec,isign = 0,newlen;
63 : g2int *coordieee;
64 824 : g2int *lipdstmpl=0;
65 : g2float *lcoordlist;
66 : gtemplate *mappds;
67 :
68 824 : ierr=0;
69 824 : *ipdstmpl=0; // NULL
70 824 : *coordlist=0; // NULL
71 :
72 824 : gbit2(cgrib,cgrib_length,&lensec,*iofst,32); // Get Length of Section
73 824 : *iofst=*iofst+32;
74 824 : gbit2(cgrib,cgrib_length,&isecnum,*iofst,8); // Get Section Number
75 824 : *iofst=*iofst+8;
76 :
77 824 : if ( isecnum != 4 ) {
78 0 : ierr=2;
79 0 : *numcoord=0;
80 0 : *mappdslen=0;
81 : // fprintf(stderr,"g2_unpack4: Not Section 4 data.\n");
82 0 : return(ierr);
83 : }
84 :
85 824 : gbit2(cgrib,cgrib_length,numcoord,*iofst,16); // Get num of coordinate values
86 824 : *iofst=*iofst+16;
87 824 : gbit2(cgrib,cgrib_length,ipdsnum,*iofst,16); // Get Prod. Def Template num.
88 824 : *iofst=*iofst+16;
89 :
90 : // Get Product Definition Template
91 824 : mappds=getpdstemplate(*ipdsnum);
92 824 : if (mappds == 0) { // undefine template
93 4 : ierr=5;
94 4 : *mappdslen=0;
95 4 : return(ierr);
96 : }
97 820 : *mappdslen=mappds->maplen;
98 820 : 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 820 : if (*mappdslen > 0) lipdstmpl=(g2int *)calloc(*mappdslen,sizeof(g2int));
105 820 : if (lipdstmpl == 0) {
106 0 : ierr=6;
107 0 : *mappdslen=0;
108 0 : *ipdstmpl=0; //NULL
109 0 : free(mappds);
110 0 : return(ierr);
111 : }
112 : else {
113 820 : *ipdstmpl=lipdstmpl;
114 : }
115 14286 : for (i=0;i<mappds->maplen;i++) {
116 13466 : nbits=abs(mappds->map[i])*8;
117 13466 : if ( mappds->map[i] >= 0 ) {
118 9421 : gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits);
119 : }
120 : else {
121 4045 : gbit2(cgrib,cgrib_length,&isign,*iofst,1);
122 4045 : gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1);
123 4045 : if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
124 : }
125 13466 : *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 820 : if ( needext ==1 ) {
135 102 : free(mappds);
136 102 : mappds=extpdstemplate(*ipdsnum,lipdstmpl);
137 102 : newlen=mappds->maplen+mappds->extlen;
138 102 : lipdstmpl=(g2int *)realloc(lipdstmpl,newlen*sizeof(g2int));
139 102 : *ipdstmpl=lipdstmpl;
140 : // Unpack the rest of the Product Definition Template
141 102 : j=0;
142 247 : 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 145 : nbits=abs(mappds->ext[j])*8;
158 145 : lipdstmpl[i] = 0;
159 145 : if ( mappds->ext[j] >= 0 ) {
160 87 : gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits);
161 : }
162 : else {
163 58 : gbit2(cgrib,cgrib_length,&isign,*iofst,1);
164 58 : gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1);
165 58 : if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i];
166 : }
167 145 : *iofst=*iofst+nbits;
168 145 : j++;
169 : }
170 102 : *mappdslen=newlen;
171 : }
172 820 : free(mappds->ext);
173 820 : free(mappds);
174 : //
175 : // Get Optional list of vertical coordinate values
176 : // after the Product Definition Template, if necessary.
177 : //
178 820 : *coordlist=0; // NULL
179 820 : if ( *numcoord != 0 ) {
180 0 : coordieee=(g2int *)calloc(*numcoord,sizeof(g2int));
181 0 : lcoordlist=(g2float *)calloc(*numcoord,sizeof(g2float));
182 0 : if (coordieee == 0 || lcoordlist == 0) {
183 0 : ierr=6;
184 0 : *numcoord=0;
185 0 : *coordlist=0; // NULL
186 0 : if( coordieee != 0 ) free(coordieee);
187 0 : if( lcoordlist != 0 ) free(lcoordlist);
188 0 : return(ierr);
189 : }
190 : else {
191 0 : *coordlist=lcoordlist;
192 : }
193 0 : gbits(cgrib,cgrib_length,coordieee,*iofst,32,0,*numcoord);
194 0 : rdieee(coordieee,*coordlist,*numcoord);
195 0 : free(coordieee);
196 0 : *iofst=*iofst+(32*(*numcoord));
197 : }
198 :
199 820 : return(ierr); // End of Section 4 processing
200 :
201 : }
|