Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}