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