/src/gdal/frmts/grib/degrib/g2clib/g2_unpack4.c
Line | Count | Source |
1 | | #include <stdio.h> |
2 | | #include <stdlib.h> |
3 | | #include <limits.h> |
4 | | #include "grib2.h" |
5 | | |
6 | | |
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 | 18.6k | { |
60 | | |
61 | 18.6k | g2int ierr,needext,i,j,nbits,isecnum = 0; |
62 | 18.6k | g2int lensec,isign = 0,newlen; |
63 | 18.6k | g2int *coordieee; |
64 | 18.6k | g2int *lipdstmpl=0; |
65 | 18.6k | g2float *lcoordlist; |
66 | 18.6k | gtemplate *mappds; |
67 | | |
68 | 18.6k | ierr=0; |
69 | 18.6k | *ipdstmpl=0; // NULL |
70 | 18.6k | *coordlist=0; // NULL |
71 | | |
72 | 18.6k | gbit2(cgrib,cgrib_length,&lensec,*iofst,32); // Get Length of Section |
73 | 18.6k | *iofst=*iofst+32; |
74 | 18.6k | gbit2(cgrib,cgrib_length,&isecnum,*iofst,8); // Get Section Number |
75 | 18.6k | *iofst=*iofst+8; |
76 | | |
77 | 18.6k | 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 | 0 | } |
84 | | |
85 | 18.6k | gbit2(cgrib,cgrib_length,numcoord,*iofst,16); // Get num of coordinate values |
86 | 18.6k | *iofst=*iofst+16; |
87 | 18.6k | gbit2(cgrib,cgrib_length,ipdsnum,*iofst,16); // Get Prod. Def Template num. |
88 | 18.6k | *iofst=*iofst+16; |
89 | | |
90 | | // Get Product Definition Template |
91 | 18.6k | mappds=getpdstemplate(*ipdsnum); |
92 | 18.6k | if (mappds == 0) { // undefine template |
93 | 1.38k | ierr=5; |
94 | 1.38k | *mappdslen=0; |
95 | 1.38k | return(ierr); |
96 | 1.38k | } |
97 | 17.3k | *mappdslen=mappds->maplen; |
98 | 17.3k | 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 | 17.3k | if (*mappdslen > 0) lipdstmpl=(g2int *)calloc(*mappdslen,sizeof(g2int)); |
105 | 17.3k | 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 | 0 | } |
112 | 17.3k | else { |
113 | 17.3k | *ipdstmpl=lipdstmpl; |
114 | 17.3k | } |
115 | 353k | for (i=0;i<mappds->maplen;i++) { |
116 | 335k | nbits=abs(mappds->map[i])*8; |
117 | 335k | if ( mappds->map[i] >= 0 ) { |
118 | 242k | gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits); |
119 | 242k | } |
120 | 93.1k | else { |
121 | 93.1k | gbit2(cgrib,cgrib_length,&isign,*iofst,1); |
122 | 93.1k | gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1); |
123 | 93.1k | if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i]; |
124 | 93.1k | } |
125 | 335k | *iofst=*iofst+nbits; |
126 | 335k | } |
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 | 17.3k | if ( needext ==1 ) { |
135 | 4.28k | free(mappds); |
136 | 4.28k | mappds=extpdstemplate(*ipdsnum,lipdstmpl); |
137 | 4.28k | newlen=mappds->maplen+mappds->extlen; |
138 | 4.28k | lipdstmpl=(g2int *)realloc(lipdstmpl,newlen*sizeof(g2int)); |
139 | 4.28k | *ipdstmpl=lipdstmpl; |
140 | | // Unpack the rest of the Product Definition Template |
141 | 4.28k | j=0; |
142 | 351k | 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 | 347k | nbits=abs(mappds->ext[j])*8; |
158 | 347k | lipdstmpl[i] = 0; |
159 | 347k | if ( mappds->ext[j] >= 0 ) { |
160 | 345k | gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst,nbits); |
161 | 345k | } |
162 | 1.30k | else { |
163 | 1.30k | gbit2(cgrib,cgrib_length,&isign,*iofst,1); |
164 | 1.30k | gbit2(cgrib,cgrib_length,lipdstmpl+i,*iofst+1,nbits-1); |
165 | 1.30k | if (isign == 1) lipdstmpl[i]=-1*lipdstmpl[i]; |
166 | 1.30k | } |
167 | 347k | *iofst=*iofst+nbits; |
168 | 347k | j++; |
169 | 347k | } |
170 | 4.28k | *mappdslen=newlen; |
171 | 4.28k | } |
172 | 17.3k | free(mappds->ext); |
173 | 17.3k | free(mappds); |
174 | | // |
175 | | // Get Optional list of vertical coordinate values |
176 | | // after the Product Definition Template, if necessary. |
177 | | // |
178 | 17.3k | *coordlist=0; // NULL |
179 | 17.3k | if ( *numcoord != 0 ) { |
180 | 5.37k | coordieee=(g2int *)calloc(*numcoord,sizeof(g2int)); |
181 | 5.37k | lcoordlist=(g2float *)calloc(*numcoord,sizeof(g2float)); |
182 | 5.37k | 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 | 0 | } |
190 | 5.37k | else { |
191 | 5.37k | *coordlist=lcoordlist; |
192 | 5.37k | } |
193 | 5.37k | gbits(cgrib,cgrib_length,coordieee,*iofst,32,0,*numcoord); |
194 | 5.37k | rdieee(coordieee,*coordlist,*numcoord); |
195 | 5.37k | free(coordieee); |
196 | 5.37k | *iofst=*iofst+(32*(*numcoord)); |
197 | 5.37k | } |
198 | | |
199 | 17.3k | return(ierr); // End of Section 4 processing |
200 | | |
201 | 17.3k | } |