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