Coverage Report

Created: 2025-07-23 09:13

/src/gdal/frmts/grib/degrib/degrib/degrib1.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * degrib1.c
3
 *
4
 * DESCRIPTION
5
 *    This file contains the main driver routines to unpack GRIB 1 files.
6
 *
7
 * HISTORY
8
 *   4/2003 Arthur Taylor (MDL / RSIS): Created.
9
 *
10
 * NOTES
11
 *   GRIB 1 files are assumed to be big endian.
12
 *****************************************************************************
13
 */
14
15
#include <assert.h>
16
#include <stdio.h>
17
#include <string.h>
18
#include <stdlib.h>
19
#include <math.h>
20
21
#include <cmath>
22
#include <limits>
23
24
#include "degrib2.h"
25
#include "myerror.h"
26
#include "myassert.h"
27
#include "tendian.h"
28
#include "scan.h"
29
#include "degrib1.h"
30
#include "metaname.h"
31
#include "clock.h"
32
#include "cpl_error.h"
33
#include "cpl_string.h"
34
35
/* default missing data value (see: bitmap GRIB1: sect3 and sect4) */
36
/* UNDEFINED is default, UNDEFINED_PRIM is desired choice. */
37
1.66M
#define UNDEFINED 9.999e20
38
24.4k
#define UNDEFINED_PRIM 9999
39
40
1.61M
#define GRIB_UNSIGN_INT3(a,b,c) ((a<<16)+(b<<8)+c)
41
1.98M
#define GRIB_UNSIGN_INT2(a,b) ((a<<8)+b)
42
1.10M
#define GRIB_SIGN_INT3(a,b,c) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 127) << 16)+(b<<8)+c))
43
786k
#define GRIB_SIGN_INT2(a,b) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 0x7f) << 8) + b))
44
45
/* various centers */
46
1.59M
#define NMC 7
47
19.5k
#define US_OTHER 9
48
40.9k
#define CPTEC 46
49
/* Canada Center */
50
4.03k
#define CMC 54
51
28.5k
#define AFWA 57
52
7.63k
#define DWD 78
53
761k
#define ECMWF 98
54
6.13k
#define ATHENS 96
55
16.7k
#define NORWAY 88
56
57
/* various subcenters */
58
2.54k
#define SUBCENTER_MDL 14
59
849
#define SUBCENTER_TDL 11
60
61
/* The idea of rean or opn is to give a warning about default choice of
62
   which table to use. */
63
#define DEF_NCEP_TABLE rean_nowarn
64
enum Def_NCEP_Table { rean, opn, rean_nowarn, opn_nowarn };
65
66
#if 0 // moved by GDAL in degrib1.h
67
68
/* For an update to these tables see:
69
 * http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html
70
 */
71
72
extern GRIB1ParmTable parm_table_ncep_opn[256];
73
extern GRIB1ParmTable parm_table_ncep_reanal[256];
74
extern GRIB1ParmTable parm_table_ncep_tdl[256];
75
extern GRIB1ParmTable parm_table_ncep_mdl[256];
76
extern GRIB1ParmTable parm_table_omb[256];
77
extern GRIB1ParmTable parm_table_nceptab_129[256];
78
extern GRIB1ParmTable parm_table_nceptab_130[256];
79
extern GRIB1ParmTable parm_table_nceptab_131[256];
80
extern GRIB1ParmTable parm_table_nceptab_133[256];
81
extern GRIB1ParmTable parm_table_nceptab_140[256];
82
extern GRIB1ParmTable parm_table_nceptab_141[256];
83
84
extern GRIB1ParmTable parm_table_nohrsc[256];
85
86
extern GRIB1ParmTable parm_table_cptec_254[256];
87
88
extern GRIB1ParmTable parm_table_afwa_000[256];
89
extern GRIB1ParmTable parm_table_afwa_001[256];
90
extern GRIB1ParmTable parm_table_afwa_002[256];
91
extern GRIB1ParmTable parm_table_afwa_003[256];
92
extern GRIB1ParmTable parm_table_afwa_010[256];
93
extern GRIB1ParmTable parm_table_afwa_011[256];
94
95
extern GRIB1ParmTable parm_table_dwd_002[256];
96
extern GRIB1ParmTable parm_table_dwd_201[256];
97
extern GRIB1ParmTable parm_table_dwd_202[256];
98
extern GRIB1ParmTable parm_table_dwd_203[256];
99
100
extern GRIB1ParmTable parm_table_ecmwf_128[256];
101
extern GRIB1ParmTable parm_table_ecmwf_129[256];
102
extern GRIB1ParmTable parm_table_ecmwf_130[256];
103
extern GRIB1ParmTable parm_table_ecmwf_131[256];
104
extern GRIB1ParmTable parm_table_ecmwf_140[256];
105
extern GRIB1ParmTable parm_table_ecmwf_150[256];
106
extern GRIB1ParmTable parm_table_ecmwf_160[256];
107
extern GRIB1ParmTable parm_table_ecmwf_170[256];
108
extern GRIB1ParmTable parm_table_ecmwf_180[256];
109
110
extern GRIB1ParmTable parm_table_athens[256];
111
112
extern GRIB1ParmTable parm_table_norway128[256];
113
114
extern GRIB1ParmTable parm_table_cmc[256];
115
116
extern GRIB1ParmTable parm_table_undefined[256];
117
118
#endif
119
120
/*****************************************************************************
121
 * Choose_ParmTable() --
122
 *
123
 * Arthur Taylor / MDL
124
 *
125
 * PURPOSE
126
 *   Chooses the correct Parameter table depending on what is in the GRIB1
127
 * message's "Product Definition Section".
128
 *
129
 * ARGUMENTS
130
 *   pdsMeta = The filled out pdsMeta data structure to base choice on. (Input)
131
 *    center = The Center that created the data (Input)
132
 * subcenter = The Sub Center that created the data (Input)
133
 *
134
 * FILES/DATABASES: None
135
 *
136
 * RETURNS: ParmTable (appropriate parameter table.)
137
 *
138
 * HISTORY
139
 *   <unknown> : wgrib library : cnames.c
140
 *   4/2003 Arthur Taylor (MDL/RSIS): Modified
141
 *  10/2005 AAT: Adjusted to take center, subcenter
142
 *
143
 * NOTES
144
 *****************************************************************************
145
 */
146
static const GRIB1ParmTable *Choose_ParmTable (pdsG1Type *pdsMeta,
147
                                         unsigned short int center,
148
                                         unsigned short int subcenter)
149
695k
{
150
695k
   int process;         /* The process ID from the GRIB1 message. */
151
152
695k
   switch (center) {
153
323k
      case NMC:
154
323k
         if (pdsMeta->mstrVersion <= 3) {
155
96.0k
            switch (subcenter) {
156
984
               case 1:
157
984
                  return &parm_table_ncep_reanal[0];
158
849
               case SUBCENTER_TDL:
159
849
                  return &parm_table_ncep_tdl[0];
160
2.54k
               case SUBCENTER_MDL:
161
2.54k
                  return &parm_table_ncep_mdl[0];
162
96.0k
            }
163
96.0k
         }
164
         /* figure out if NCEP opn or reanalysis */
165
318k
         switch (pdsMeta->mstrVersion) {
166
29.7k
            case 0:
167
29.7k
               return &parm_table_ncep_opn[0];
168
14.4k
            case 1:
169
44.1k
            case 2:
170
44.1k
               process = pdsMeta->genProcess;
171
44.1k
               if ((subcenter != 0) || ((process != 80) && (process != 180))) {
172
37.6k
                  return &parm_table_ncep_opn[0];
173
37.6k
               }
174
#if 0
175
               /* At this point could be either the opn or reanalysis table */
176
               switch (DEF_NCEP_TABLE) {
177
                  case opn_nowarn:
178
                     return &parm_table_ncep_opn[0];
179
                  case rean_nowarn:
180
                     return &parm_table_ncep_reanal[0];
181
               }
182
               break;
183
#else
184
               // ERO: this is the non convoluted version of the above code
185
6.45k
               return &parm_table_ncep_reanal[0];
186
0
#endif
187
17.7k
            case 3:
188
17.7k
               return &parm_table_ncep_opn[0];
189
48.7k
            case 128:
190
48.7k
               return &parm_table_omb[0];
191
17.8k
            case 129:
192
17.8k
               return &parm_table_nceptab_129[0];
193
8.73k
            case 130:
194
8.73k
               return &parm_table_nceptab_130[0];
195
1.99k
            case 131:
196
1.99k
               return &parm_table_nceptab_131[0];
197
13.0k
            case 133:
198
13.0k
               return &parm_table_nceptab_133[0];
199
1.69k
            case 140:
200
1.69k
               return &parm_table_nceptab_140[0];
201
5.44k
            case 141:
202
5.44k
               return &parm_table_nceptab_141[0];
203
318k
         }
204
129k
         break;
205
129k
      case AFWA:
206
28.5k
         switch (subcenter) {
207
16.8k
            case 0:
208
16.8k
               return &parm_table_afwa_000[0];
209
17
            case 1:
210
17
            case 4:
211
17
               return &parm_table_afwa_001[0];
212
0
            case 2:
213
0
               return &parm_table_afwa_002[0];
214
35
            case 3:
215
35
               return &parm_table_afwa_003[0];
216
1.38k
            case 10:
217
1.38k
               return &parm_table_afwa_010[0];
218
0
            case 11:
219
0
               return &parm_table_afwa_011[0];
220
/*            case 5:*/
221
               /* Didn't have a table 5. */
222
28.5k
         }
223
10.2k
         break;
224
70.1k
      case ECMWF:
225
70.1k
         switch (pdsMeta->mstrVersion) {
226
12.3k
            case 128:
227
12.3k
               return &parm_table_ecmwf_128[0];
228
17.6k
            case 129:
229
17.6k
               return &parm_table_ecmwf_129[0];
230
13.7k
            case 130:
231
13.7k
               return &parm_table_ecmwf_130[0];
232
12.2k
            case 131:
233
12.2k
               return &parm_table_ecmwf_131[0];
234
5.00k
            case 140:
235
5.00k
               return &parm_table_ecmwf_140[0];
236
456
            case 150:
237
456
               return &parm_table_ecmwf_150[0];
238
3.10k
            case 160:
239
3.10k
               return &parm_table_ecmwf_160[0];
240
352
            case 170:
241
352
               return &parm_table_ecmwf_170[0];
242
71
            case 180:
243
71
               return &parm_table_ecmwf_180[0];
244
1.07k
            case 210:
245
1.07k
               return &parm_table_ecmwf_210[0];
246
0
            case 215:
247
0
               return &parm_table_ecmwf_215[0];
248
0
            case 217:
249
0
               return &parm_table_ecmwf_217[0];
250
1
            case 218:
251
1
               return &parm_table_ecmwf_218[0];
252
1.47k
            case 228:
253
1.47k
               return &parm_table_ecmwf_228[0];
254
70.1k
         }
255
2.66k
         break;
256
7.63k
      case DWD:
257
7.63k
         switch (pdsMeta->mstrVersion) {
258
554
            case 2:
259
554
               return &parm_table_dwd_002[0];
260
1.59k
            case 201:
261
1.59k
               return &parm_table_dwd_201[0];
262
113
            case 202:
263
113
               return &parm_table_dwd_202[0];
264
695
            case 203:
265
695
               return &parm_table_dwd_203[0];
266
7.63k
         }
267
4.67k
         break;
268
40.9k
      case CPTEC:
269
40.9k
         switch (pdsMeta->mstrVersion) {
270
35.3k
            case 254:
271
35.3k
               return &parm_table_cptec_254[0];
272
40.9k
         }
273
5.62k
         break;
274
19.5k
      case US_OTHER:
275
19.5k
         switch (subcenter) {
276
1.39k
            case 163:
277
1.39k
               return &parm_table_nohrsc[0];
278
            /* Based on 11/7/2006 email with Rob Doornbos, mimic'd what wgrib
279
             * did which was to use parm_table_ncep_opn. */
280
322
            case 161:
281
322
               return &parm_table_ncep_opn[0];
282
19.5k
         }
283
17.8k
         break;
284
17.8k
      case ATHENS:
285
6.13k
         return &parm_table_athens[0];
286
0
         break;
287
16.7k
      case NORWAY:
288
16.7k
         if (pdsMeta->mstrVersion == 128) {
289
13.7k
            return &parm_table_norway128[0];
290
13.7k
         }
291
3.05k
         break;
292
4.03k
      case CMC:
293
4.03k
         return &parm_table_cmc[0];
294
0
         break;
295
695k
   }
296
351k
   if (pdsMeta->mstrVersion > 3) {
297
266k
      CPLError( CE_Warning, CPLE_AppDefined, "GRIB: Don't understand the parameter table, since center %d-%d used\n"
298
266k
              "parameter table version %d instead of 3 (international exchange).\n"
299
266k
              "Using default for now (which might lead to erroneous interpretation), but please email arthur.taylor@noaa.gov\n"
300
266k
              "about adding this table to his 'degrib1.c' and 'grib1tab.c' files.",
301
266k
              center, subcenter, pdsMeta->mstrVersion);
302
266k
   }
303
351k
   if (pdsMeta->cat > 127) {
304
254k
      CPLError(CE_Warning, CPLE_AppDefined, "GRIB: Parameter %d is > 127, so it falls in the local use section of\n"
305
254k
              "the parameter table (and is undefined on the international table.\n"
306
254k
              "Using default for now(which might lead to erroneous interpretation), but please email arthur.taylor@noaa.gov\n"
307
254k
              "about adding this table to his 'degrib1.c' and 'grib1tab.c' files.",
308
254k
              pdsMeta->cat);
309
254k
   }
310
351k
   return &parm_table_undefined[0];
311
695k
}
312
313
/*****************************************************************************
314
 * GRIB1_Table2LookUp() --
315
 *
316
 * Arthur Taylor / MDL
317
 *
318
 * PURPOSE
319
 *   Returns the variable name (type of data) and comment (longer form of the
320
 * name) for the data that is in the GRIB1 message.
321
 *
322
 * ARGUMENTS
323
 *      name = A pointer to the resulting short name. (Output)
324
 *   comment = A pointer to the resulting long name. (Output)
325
 *   pdsMeta = The filled out pdsMeta data structure to base choice on. (Input)
326
 *    center = The Center that created the data (Input)
327
 * subcenter = The Sub Center that created the data (Input)
328
 *
329
 * FILES/DATABASES: None
330
 *
331
 * RETURNS: void
332
 *
333
 * HISTORY
334
 *   4/2003 Arthur Taylor (MDL/RSIS): Created
335
 *  10/2005 AAT: Adjusted to take center, subcenter
336
 *
337
 * NOTES
338
 *****************************************************************************
339
 */
340
static void GRIB1_Table2LookUp (pdsG1Type *pdsMeta, const char **name,
341
                                const char **comment, const char **unit,
342
                                int *convert,
343
                                unsigned short int center,
344
                                unsigned short int subcenter)
345
695k
{
346
695k
   const GRIB1ParmTable *table; /* The parameter table chosen by the pdsMeta data */
347
348
695k
   table = Choose_ParmTable (pdsMeta, center, subcenter);
349
695k
   if ((center == NMC) && (pdsMeta->mstrVersion == 129)
350
695k
       && (pdsMeta->cat == 180)) {
351
7.62k
      if (pdsMeta->timeRange == 3) {
352
977
         *name = "AVGOZCON";
353
977
         *comment = "Average Ozone Concentration";
354
977
         *unit = "PPB";
355
977
         *convert = UC_NONE;
356
977
         return;
357
977
      }
358
7.62k
   }
359
694k
   *name = table[pdsMeta->cat].name;
360
694k
   if( strcmp(*name, CPLSPrintf("var%d", pdsMeta->cat)) == 0 )
361
341k
   {
362
341k
       if( center == ECMWF )
363
49.6k
           *name = CPLSPrintf("var%d of table %d of center ECMWF", pdsMeta->cat, pdsMeta->mstrVersion);
364
291k
       else
365
291k
           *name = CPLSPrintf("var%d of table %d of center %d", pdsMeta->cat, pdsMeta->mstrVersion, center);
366
341k
   }
367
694k
   *comment = table[pdsMeta->cat].comment;
368
694k
   *unit = table[pdsMeta->cat].unit;
369
694k
   *convert = table[pdsMeta->cat].convert;
370
/*   printf ("%s %s %s\n", *name, *comment, *unit);*/
371
694k
}
372
373
/* Similar to metaname.c :: ParseLevelName() */
374
static void GRIB1_Table3LookUp (pdsG1Type *pdsMeta, char **shortLevelName,
375
                                char **longLevelName)
376
585k
{
377
585k
   uChar type = pdsMeta->levelType;
378
585k
   uChar level1, level2;
379
380
585k
   free (*shortLevelName);
381
585k
   *shortLevelName = nullptr;
382
585k
   free (*longLevelName);
383
585k
   *longLevelName = nullptr;
384
   /* Find out if val is a 2 part value or not */
385
585k
   if (GRIB1Surface[type].f_twoPart) {
386
41.3k
      level1 = (pdsMeta->levelVal >> 8);
387
41.3k
      level2 = (pdsMeta->levelVal & 0xff);
388
41.3k
      reallocSprintf (shortLevelName, "%d-%d-%s", level1, level2,
389
41.3k
                      GRIB1Surface[type].name);
390
41.3k
      reallocSprintf (longLevelName, "%d-%d[%s] %s (%s)", level1, level2,
391
41.3k
                      GRIB1Surface[type].unit, GRIB1Surface[type].name,
392
41.3k
                      GRIB1Surface[type].comment);
393
544k
   } else {
394
544k
      reallocSprintf (shortLevelName, "%d-%s", pdsMeta->levelVal,
395
544k
                      GRIB1Surface[type].name);
396
544k
      reallocSprintf (longLevelName, "%d[%s] %s (%s)", pdsMeta->levelVal,
397
544k
                      GRIB1Surface[type].unit, GRIB1Surface[type].name,
398
544k
                      GRIB1Surface[type].comment);
399
544k
   }
400
585k
}
401
402
/*****************************************************************************
403
 * fval_360() --
404
 *
405
 * Albion Taylor / ARL
406
 *
407
 * PURPOSE
408
 *   Converts an IBM360 floating point number to an IEEE floating point
409
 * number.  The IBM floating point spec represents the fraction as the last
410
 * 3 bytes of the number, with 0xffffff being just shy of 1.0.  The first byte
411
 * leads with a sign bit, and the last seven bits represent the powers of 16
412
 * (not 2), with a bias of 0x40 giving 16^0.
413
 *
414
 * ARGUMENTS
415
 * aval = A sInt4 containing the original IBM 360 number. (Input)
416
 *
417
 * FILES/DATABASES: None
418
 *
419
 * RETURNS: double = the value that aval represents.
420
 *
421
 * HISTORY
422
 *   <unknown> Albion Taylor (ARL): Created
423
 *   4/2003 Arthur Taylor (MDL/RSIS): Cleaned up.
424
 *   5/2003 AAT: some kind of Bug due to optimizations...
425
 *          -1055916032 => 0 instead of -1
426
 *
427
 * NOTES
428
 *****************************************************************************
429
 */
430
static double fval_360 (uInt4 aval)
431
107k
{
432
107k
   short int ptr[4];
433
107k
#ifdef LITTLE_ENDIAN
434
107k
   ptr[3] = ((((aval >> 24) & 0x7f) << 2) + (0x3ff - 0x100)) << 4;
435
107k
   ptr[2] = 0;
436
107k
   ptr[1] = 0;
437
107k
   ptr[0] = 0;
438
#else
439
   ptr[0] = ((((aval >> 24) & 0x7f) << 2) + (0x3ff - 0x100)) << 4;
440
   ptr[1] = 0;
441
   ptr[2] = 0;
442
   ptr[3] = 0;
443
#endif
444
107k
   double pow16;
445
107k
   memcpy(&pow16, ptr, 8);
446
107k
   return ((aval & 0x80000000) ? -pow16 : pow16) *
447
107k
         (aval & 0xffffff) / ((double) 0x1000000);
448
107k
}
449
450
/*****************************************************************************
451
 * ReadGrib1Sect1() --
452
 *
453
 * Arthur Taylor / MDL
454
 *
455
 * PURPOSE
456
 *   Parses the GRIB1 "Product Definition Section" or section 1, filling out
457
 * the pdsMeta data structure.
458
 *
459
 * ARGUMENTS
460
 *       pds = The compressed part of the message dealing with "PDS". (Input)
461
 *    pdsLen = Size of pds in bytes. (Input)
462
 *   gribLen = The total length of the GRIB1 message. (Input)
463
 *    curLoc = Current location in the GRIB1 message. (Output)
464
 *   pdsMeta = The filled out pdsMeta data structure. (Output)
465
 *     f_gds = boolean if there is a Grid Definition Section. (Output)
466
 *    gridID = The Grid ID. (Output)
467
 *     f_bms = boolean if there is a Bitmap Section. (Output)
468
 *       DSF = Decimal Scale Factor for unpacking the data. (Output)
469
 *    center = The Center that created the data (Output)
470
 * subcenter = The Sub Center that created the data (Output)
471
 *
472
 * FILES/DATABASES: None
473
 *
474
 * RETURNS: int (could use errSprintf())
475
 *  0 = OK
476
 * -1 = gribLen is too small.
477
 *
478
 * HISTORY
479
 *   4/2003 Arthur Taylor (MDL/RSIS): Created.
480
 *   5/2004 AAT: Paid attention to table 5 (Time range indicator) and which of
481
 *          P1 and P2 are the valid times.
482
 *  10/2005 AAT: Adjusted to take center, subcenter
483
 *
484
 * NOTES
485
 *****************************************************************************
486
 */
487
static int ReadGrib1Sect1 (uChar *pds, uInt4 pdsLen, uInt4 gribLen, uInt4 *curLoc,
488
                           pdsG1Type *pdsMeta, char *f_gds, uChar *gridID,
489
                           char *f_bms, short int *DSF,
490
                           unsigned short int *center,
491
                           unsigned short int *subcenter)
492
728k
{
493
728k
   uInt4 sectLen;       /* Length in bytes of the current section. */
494
728k
   int year;            /* The year of the GRIB1 Message. */
495
728k
   double P1_DeltaTime; /* Used to parse the time for P1 */
496
728k
   double P2_DeltaTime; /* Used to parse the time for P2 */
497
728k
   uInt4 uli_temp;
498
#ifdef DEBUG
499
/*
500
   int i;
501
*/
502
#endif
503
   /* We will read the first required 28 bytes */
504
728k
   if( pdsLen < 28 )
505
19
       return -1;
506
507
728k
   sectLen = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
508
728k
   if( sectLen > pdsLen )
509
0
       return -1;
510
#ifdef DEBUG
511
/*
512
   printf ("Section 1 length = %ld\n", sectLen);
513
   for (i = 0; i < sectLen; i++) {
514
      printf ("Sect1: item %d = %d\n", i + 1, pds[i]);
515
   }
516
   printf ("Century is item 25\n");
517
*/
518
#endif
519
728k
   *curLoc += sectLen;
520
728k
   if (*curLoc > gribLen) {
521
0
      errSprintf ("Ran out of data in PDS (GRIB 1 Section 1)\n");
522
0
      return -1;
523
0
   }
524
728k
   pds += 3;
525
728k
   pdsMeta->mstrVersion = *(pds++);
526
728k
   *center = *(pds++);
527
728k
   pdsMeta->genProcess = *(pds++);
528
728k
   *gridID = *(pds++);
529
728k
   *f_gds = GRIB2BIT_1 & *pds;
530
728k
   *f_bms = GRIB2BIT_2 & *pds;
531
728k
   pds++;
532
728k
   pdsMeta->cat = *(pds++);
533
728k
   pdsMeta->levelType = *(pds++);
534
728k
   pdsMeta->levelVal = GRIB_UNSIGN_INT2 (*pds, pds[1]);
535
728k
   pds += 2;
536
728k
   if (*pds == 0) {
537
      /* The 12 is because we have increased pds by 12. (but 25 is in
538
       * reference of 1..25, so we need another -1) */
539
188k
      year = (pds[25 - 13] * 100);
540
539k
   } else {
541
      /* The 12 is because we have increased pds by 12. (but 25 is in
542
       * reference of 1..25, so we need another -1) */
543
539k
      year = *pds + ((pds[25 - 13] - 1) * 100);
544
539k
   }
545
546
728k
   if (ParseTime (&(pdsMeta->refTime), year, pds[1], pds[2], pds[3], pds[4],
547
728k
                  0) != 0) {
548
1.79k
      preErrSprintf ("Error In call to ParseTime\n");
549
1.79k
      errSprintf ("(Probably a corrupt file)\n");
550
1.79k
      return -1;
551
1.79k
   }
552
726k
   pds += 5;
553
726k
   pdsMeta->timeRange = pds[3];
554
726k
   if (ParseSect4Time2secV1 (pds[1], *pds, &P1_DeltaTime) == 0) {
555
441k
      pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
556
441k
   } else {
557
285k
      pdsMeta->P1 = pdsMeta->refTime;
558
285k
      printf ("Warning! : Can't figure out time unit of %u\n", *pds);
559
285k
   }
560
726k
   if (ParseSect4Time2secV1 (pds[2], *pds, &P2_DeltaTime) == 0) {
561
441k
      pdsMeta->P2 = pdsMeta->refTime + P2_DeltaTime;
562
441k
   } else {
563
285k
      pdsMeta->P2 = pdsMeta->refTime;
564
285k
      printf ("Warning! : Can't figure out time unit of %u\n", *pds);
565
285k
   }
566
   /* The following is based on Table 5. */
567
   /* Note: For ensemble forecasts, 119 has meaning. */
568
726k
   switch (pdsMeta->timeRange) {
569
299k
      case 0:
570
361k
      case 1:
571
368k
      case 113:
572
374k
      case 114:
573
378k
      case 115:
574
387k
      case 116:
575
393k
      case 117:
576
399k
      case 118:
577
401k
      case 123:
578
402k
      case 124:
579
402k
         pdsMeta->validTime = pdsMeta->P1;
580
402k
         break;
581
10.7k
      case 2:
582
         /* Puzzling case. */
583
10.7k
         pdsMeta->validTime = pdsMeta->P2;
584
10.7k
         break;
585
23.0k
      case 3:
586
45.9k
      case 4:
587
57.1k
      case 5:
588
64.8k
      case 51:
589
64.8k
         pdsMeta->validTime = pdsMeta->P2;
590
64.8k
         break;
591
64.3k
      case 10:
592
64.3k
         if (ParseSect4Time2secV1 (GRIB_UNSIGN_INT2 (pds[1], pds[2]), *pds,
593
64.3k
                                   &P1_DeltaTime) == 0) {
594
54.4k
            pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
595
54.4k
         } else {
596
9.85k
            pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime;
597
9.85k
            printf ("Warning! : Can't figure out time unit of %u\n", *pds);
598
9.85k
         }
599
64.3k
         pdsMeta->validTime = pdsMeta->P1;
600
64.3k
         break;
601
184k
      default:
602
184k
         pdsMeta->validTime = pdsMeta->P1;
603
726k
   }
604
726k
   pds += 4;
605
726k
   pdsMeta->Average = GRIB_UNSIGN_INT2 (*pds, pds[1]);
606
726k
   pds += 2;
607
726k
   pdsMeta->numberMissing = *(pds++);
608
   /* Skip over centry of reference time. */
609
726k
   pds++;
610
726k
   *subcenter = *(pds++);
611
726k
   *DSF = GRIB_SIGN_INT2 (*pds, pds[1]);
612
726k
   pds += 2;
613
726k
   pdsMeta->f_hasEns = 0;
614
726k
   pdsMeta->f_hasProb = 0;
615
726k
   pdsMeta->f_hasCluster = 0;
616
726k
   if (sectLen < 41) {
617
319k
      return 0;
618
319k
   }
619
   /* Following is based on:
620
    * http://www.emc.ncep.noaa.gov/gmb/ens/info/ens_grib.html */
621
407k
   if ((*center == NMC) && (*subcenter == 2)) {
622
57.7k
      if (sectLen < 45) {
623
2.63k
         printf ("Warning! Problems with Ensemble section\n");
624
2.63k
         return 0;
625
2.63k
      }
626
55.1k
      pdsMeta->f_hasEns = 1;
627
55.1k
      pdsMeta->ens.BitFlag = *(pds++);
628
/*      octet21 = pdsMeta->timeRange; = 119 has meaning now */
629
55.1k
      pds += 11;
630
55.1k
      pdsMeta->ens.Application = *(pds++);
631
55.1k
      pdsMeta->ens.Type = *(pds++);
632
55.1k
      pdsMeta->ens.Number = *(pds++);
633
55.1k
      pdsMeta->ens.ProdID = *(pds++);
634
55.1k
      pdsMeta->ens.Smooth = *(pds++);
635
55.1k
      if ((pdsMeta->cat == 191) || (pdsMeta->cat == 192) ||
636
55.1k
          (pdsMeta->cat == 193)) {
637
24.7k
         if (sectLen < 60) {
638
6.82k
            printf ("Warning! Problems with Ensemble Probability section\n");
639
6.82k
            return 0;
640
6.82k
         }
641
17.9k
         pdsMeta->f_hasProb = 1;
642
17.9k
         pdsMeta->prob.Cat = pdsMeta->cat;
643
17.9k
         pdsMeta->cat = *(pds++);
644
17.9k
         pdsMeta->prob.Type = *(pds++);
645
17.9k
         MEMCPY_BIG (&uli_temp, pds, sizeof (sInt4));
646
17.9k
         pdsMeta->prob.lower = fval_360 (uli_temp);
647
17.9k
         pds += 4;
648
17.9k
         MEMCPY_BIG (&uli_temp, pds, sizeof (sInt4));
649
17.9k
         pdsMeta->prob.upper = fval_360 (uli_temp);
650
17.9k
         pds += 4;
651
17.9k
         pds += 4;
652
17.9k
      }
653
48.3k
      if ((pdsMeta->ens.Type == 4) || (pdsMeta->ens.Type == 5)) {
654
         /* 87 ... 100 was reserved, but may not be encoded */
655
13.4k
         if ((sectLen < 100) && (sectLen != 86)) {
656
12.5k
            printf ("Warning! Problems with Ensemble Clustering section\n");
657
12.5k
            printf ("Section length == %u\n", sectLen);
658
12.5k
            return 0;
659
12.5k
         }
660
944
         if (pdsMeta->f_hasProb == 0) {
661
265
            pds += 14;
662
265
         }
663
944
         pdsMeta->f_hasCluster = 1;
664
944
         pdsMeta->cluster.ensSize = *(pds++);
665
944
         pdsMeta->cluster.clusterSize = *(pds++);
666
944
         pdsMeta->cluster.Num = *(pds++);
667
944
         pdsMeta->cluster.Method = *(pds++);
668
944
         pdsMeta->cluster.NorLat = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
669
944
         pdsMeta->cluster.NorLat = pdsMeta->cluster.NorLat / 1000.;
670
944
         pds += 3;
671
944
         pdsMeta->cluster.SouLat = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
672
944
         pdsMeta->cluster.SouLat = pdsMeta->cluster.SouLat / 1000.;
673
944
         pds += 3;
674
944
         pdsMeta->cluster.EasLon = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
675
944
         pdsMeta->cluster.EasLon = pdsMeta->cluster.EasLon / 1000.;
676
944
         pds += 3;
677
944
         pdsMeta->cluster.WesLon = GRIB_UNSIGN_INT3 (*pds, pds[1], pds[2]);
678
944
         pdsMeta->cluster.WesLon = pdsMeta->cluster.WesLon / 1000.;
679
944
         pds += 3;
680
944
         memcpy (pdsMeta->cluster.Member, pds, 10);
681
944
         pdsMeta->cluster.Member[10] = '\0';
682
944
      }
683
      /* Following based on:
684
       * http://www.ecmwf.int/publications/manuals/libraries/gribex/
685
       * localGRIBUsage.html */
686
349k
   } else if (*center == ECMWF) {
687
58.0k
      if (sectLen < 45) {
688
29.0k
         printf ("Warning! Problems with ECMWF PDS extension\n");
689
29.0k
         return 0;
690
29.0k
      }
691
      /*
692
      sInt4 i_temp;
693
      pds += 12;
694
      i_temp = GRIB_SIGN_INT2 (pds[3], pds[4]);
695
      printf ("ID %d Class %d Type %d Stream %d", pds[0], pds[1], pds[2],
696
              i_temp);
697
      pds += 5;
698
      printf (" Ver %c%c%c%c, ", pds[0], pds[1], pds[2], pds[3]);
699
      pds += 4;
700
      printf ("Octet-50 %d, Octet-51 %d SectLen %d\n", pds[0], pds[1],
701
              sectLen);
702
      */
703
291k
   } else {
704
291k
      printf ("Un-handled possible ensemble section center %u "
705
291k
              "subcenter %u\n", *center, *subcenter);
706
291k
   }
707
356k
   return 0;
708
407k
}
709
710
/*****************************************************************************
711
 * Grib1_Inventory() --
712
 *
713
 * Arthur Taylor / MDL
714
 *
715
 * PURPOSE
716
 *   Parses the GRIB1 "Product Definition Section" for enough information to
717
 * fill out the inventory data structure so we can do a simple inventory on
718
 * the file in a similar way to how we did it for GRIB2.
719
 *
720
 * ARGUMENTS
721
 *      fp = An opened GRIB2 file already at the correct message. (Input)
722
 * gribLen = The total length of the GRIB1 message. (Input)
723
 *     inv = The inventory data structure that we need to fill. (Output)
724
 *
725
 * FILES/DATABASES: None
726
 *
727
 * RETURNS: int (could use errSprintf())
728
 *  0 = OK
729
 * -1 = gribLen is too small.
730
 *
731
 * HISTORY
732
 *   4/2003 Arthur Taylor (MDL/RSIS): Created.
733
 *
734
 * NOTES
735
 *****************************************************************************
736
 */
737
int GRIB1_Inventory (VSILFILE *fp, uInt4 gribLen, inventoryType *inv)
738
551k
{
739
551k
   uChar temp[3];        /* Used to determine the section length. */
740
551k
   uInt4 sectLen;       /* Length in bytes of the current section. */
741
551k
   uChar *pds;          /* The part of the message dealing with the PDS. */
742
551k
   pdsG1Type pdsMeta;   /* The pds parsed into a usable data structure. */
743
551k
   char f_gds;          /* flag if there is a gds section. */
744
551k
   char f_bms;          /* flag if there is a bms section. */
745
551k
   short int DSF;       /* Decimal Scale Factor for unpacking the data. */
746
551k
   uChar gridID;        /* Which GDS specs to use. */
747
551k
   const char *varName; /* The name of the data stored in the grid. */
748
551k
   const char *varComment; /* Extra comments about the data stored in grid. */
749
551k
   const char *varUnit; /* Holds the name of the unit [K] [%] .. etc */
750
551k
   int convert;         /* Conversion method for this variable's unit. */
751
551k
   uInt4 curLoc;        /* Where we are in the current GRIB message. */
752
551k
   unsigned short int center; /* The Center that created the data */
753
551k
   unsigned short int subcenter; /* The Sub Center that created the data */
754
755
551k
   curLoc = 8;
756
551k
   if (VSIFReadL(temp, sizeof (char), 3, fp) != 3) {
757
37
      errSprintf ("Ran out of file.\n");
758
37
      return -1;
759
37
   }
760
551k
   sectLen = GRIB_UNSIGN_INT3 (*temp, temp[1], temp[2]);
761
551k
   if (curLoc + sectLen > gribLen) {
762
742
      errSprintf ("Ran out of data in PDS (GRIB1_Inventory)\n");
763
742
      return -1;
764
742
   }
765
550k
   if( sectLen < 3 )
766
503
   {
767
503
       errSprintf ("Invalid sectLen.\n");
768
503
       return -1;
769
503
   }
770
550k
   pds = (uChar *) malloc (sectLen * sizeof (uChar));
771
550k
   if( pds == nullptr )
772
0
   {
773
0
       errSprintf ("Ran out of memory.\n");
774
0
       return -1;
775
0
   }
776
550k
   *pds = *temp;
777
550k
   pds[1] = temp[1];
778
550k
   pds[2] = temp[2];
779
550k
   if (VSIFReadL(pds + 3, sizeof (char), sectLen - 3, fp) + 3 != sectLen) {
780
315
      errSprintf ("Ran out of file.\n");
781
315
      free (pds);
782
315
      return -1;
783
315
   }
784
785
549k
   if (ReadGrib1Sect1 (pds, sectLen, gribLen, &curLoc, &pdsMeta, &f_gds, &gridID,
786
549k
                       &f_bms, &DSF, &center, &subcenter) != 0) {
787
1.81k
      preErrSprintf ("Inside GRIB1_Inventory\n");
788
1.81k
      free (pds);
789
1.81k
      return -1;
790
1.81k
   }
791
548k
   free (pds);
792
548k
   inv->refTime = pdsMeta.refTime;
793
548k
   inv->validTime = pdsMeta.validTime;
794
548k
   inv->foreSec = inv->validTime - inv->refTime;
795
548k
   GRIB1_Table2LookUp (&(pdsMeta), &varName, &varComment, &varUnit,
796
548k
                       &convert, center, subcenter);
797
548k
   inv->element = (char *) malloc ((1 + strlen (varName)) * sizeof (char));
798
548k
   strcpy (inv->element, varName);
799
548k
   inv->unitName = (char *) malloc ((1 + 2 + strlen (varUnit)) *
800
548k
                                    sizeof (char));
801
548k
   snprintf (inv->unitName, (1 + 2 + strlen (varUnit)) *
802
548k
                                    sizeof (char), "[%s]", varUnit);
803
548k
   inv->comment = (char *) malloc ((1 + strlen (varComment) +
804
548k
                                    strlen (varUnit) + 2 + 1) *
805
548k
                                   sizeof (char));
806
548k
   snprintf (inv->comment, (1 + strlen (varComment) +
807
548k
                                    strlen (varUnit) + 2 + 1) *
808
548k
                                   sizeof (char),
809
548k
             "%s [%s]", varComment, varUnit);
810
811
548k
   GRIB1_Table3LookUp (&(pdsMeta), &(inv->shortFstLevel),
812
548k
                       &(inv->longFstLevel));
813
814
   /* Get to the end of the GRIB1 message. */
815
   /* (inventory.c : GRIB2Inventory), is responsible for this. */
816
   /* fseek (fp, gribLen - sectLen, SEEK_CUR); */
817
548k
   return 0;
818
549k
}
819
820
int GRIB1_RefTime (VSILFILE *fp, uInt4 gribLen, double *refTime)
821
0
{
822
0
   uChar temp[3];        /* Used to determine the section length. */
823
0
   uInt4 sectLen;       /* Length in bytes of the current section. */
824
0
   uChar *pds;          /* The part of the message dealing with the PDS. */
825
0
   pdsG1Type pdsMeta;   /* The pds parsed into a usable data structure. */
826
0
   char f_gds;          /* flag if there is a gds section. */
827
0
   char f_bms;          /* flag if there is a bms section. */
828
0
   short int DSF;       /* Decimal Scale Factor for unpacking the data. */
829
0
   uChar gridID;        /* Which GDS specs to use. */
830
0
   uInt4 curLoc;        /* Where we are in the current GRIB message. */
831
0
   unsigned short int center; /* The Center that created the data */
832
0
   unsigned short int subcenter; /* The Sub Center that created the data */
833
834
0
   curLoc = 8;
835
0
   if (VSIFReadL (temp, sizeof (char), 3, fp) != 3) {
836
0
      errSprintf ("Ran out of file.\n");
837
0
      return -1;
838
0
   }
839
0
   sectLen = GRIB_UNSIGN_INT3 (*temp, temp[1], temp[2]);
840
0
   if (curLoc + sectLen > gribLen) {
841
0
      errSprintf ("Ran out of data in PDS (GRIB1_Inventory)\n");
842
0
      return -1;
843
0
   }
844
0
   pds = (uChar *) malloc (sectLen * sizeof (uChar));
845
0
   if(!pds)
846
0
   {
847
0
       errSprintf("Out of memory");
848
0
       return -1;
849
0
   }
850
0
   *pds = *temp;
851
0
   pds[1] = temp[1];
852
0
   pds[2] = temp[2];
853
0
   if (VSIFReadL (pds + 3, sizeof (char), sectLen - 3, fp) + 3 != sectLen) {
854
0
      errSprintf ("Ran out of file.\n");
855
0
      free (pds);
856
0
      return -1;
857
0
   }
858
859
0
   if (ReadGrib1Sect1 (pds, sectLen, gribLen, &curLoc, &pdsMeta, &f_gds, &gridID,
860
0
                       &f_bms, &DSF, &center, &subcenter) != 0) {
861
0
      preErrSprintf ("Inside GRIB1_Inventory\n");
862
0
      free (pds);
863
0
      return -1;
864
0
   }
865
0
   free (pds);
866
867
0
   *refTime = pdsMeta.refTime;
868
869
   /* Get to the end of the GRIB1 message. */
870
   /* (inventory.c : GRIB2Inventory), is responsible for this. */
871
   /* fseek (fp, gribLen - sectLen, SEEK_CUR); */
872
0
   return 0;
873
0
}
874
875
/*****************************************************************************
876
 * ReadGrib1Sect2() --
877
 *
878
 * Arthur Taylor / MDL
879
 *
880
 * PURPOSE
881
 *   Parses the GRIB1 "Grid Definition Section" or section 2, filling out
882
 * the gdsMeta data structure.
883
 *
884
 * ARGUMENTS
885
 *     gds = The compressed part of the message dealing with "GDS". (Input)
886
 * gribLen = The total length of the GRIB1 message. (Input)
887
 *  curLoc = Current location in the GRIB1 message. (Output)
888
 * gdsMeta = The filled out gdsMeta data structure. (Output)
889
 *
890
 * FILES/DATABASES: None
891
 *
892
 * RETURNS: int (could use errSprintf())
893
 *  0 = OK
894
 * -1 = gribLen is too small.
895
 * -2 = unexpected values in gds.
896
 *
897
 * HISTORY
898
 *   4/2003 Arthur Taylor (MDL/RSIS): Created.
899
 *  12/2003 AAT: adas data encoder seems to have # of vertical data = 1, but
900
 *        parameters of vertical data = 255, which doesn't make sense.
901
 *        Changed the error from "fatal" to a warning in debug mode.
902
 *   6/2004 AAT: Modified to allow "extended" lat/lon grids (i.e. stretched or
903
 *        stretched and rotated).
904
 *
905
 * NOTES
906
 *****************************************************************************
907
 */
908
static int ReadGrib1Sect2 (uChar *gds, uInt4 gribLen, uInt4 *curLoc,
909
                           gdsType *gdsMeta)
910
176k
{
911
176k
   uInt4 sectLen;       /* Length in bytes of the current section. */
912
176k
   int gridType;        /* Which type of grid. (see enumerated types). */
913
176k
   double unit = 1e-3; /* Used for converting to the correct unit. */
914
176k
   uInt4 uli_temp;      /* Used for reading a GRIB1 float. */
915
176k
   int i;
916
176k
   int f_allZero;       /* Used to find out if the "lat/lon" extension part
917
                         * is all 0 hence missing. */
918
176k
   int f_allOne;        /* Used to find out if the "lat/lon" extension part
919
                         * is all 1 hence missing. */
920
921
176k
   if( gribLen < *curLoc || gribLen - *curLoc < 6 ) {
922
74
      errSprintf ("Ran out of data in GDS (GRIB 1 Section 2)\n");
923
74
      return -1;
924
74
   }
925
176k
   sectLen = GRIB_UNSIGN_INT3 (*gds, gds[1], gds[2]);
926
#ifdef DEBUG
927
/*
928
   printf ("Section 2 length = %ld\n", sectLen);
929
*/
930
#endif
931
176k
   *curLoc += sectLen;
932
176k
   if (*curLoc > gribLen) {
933
5.83k
      errSprintf ("Ran out of data in GDS (GRIB 1 Section 2)\n");
934
5.83k
      return -1;
935
5.83k
   }
936
170k
   gds += 3;
937
/*
938
#ifdef DEBUG
939
   if ((*gds != 0) || (gds[1] != 255)) {
940
      printf ("GRIB1 GDS: Expect (NV = 0) != %d, (PV = 255) != %d\n",
941
              *gds, gds[1]);
942
      errSprintf ("SectLen == %ld\n", sectLen);
943
      errSprintf ("GridType == %d\n", gds[2]);
944
   }
945
#endif
946
*/
947
#ifdef DEBUG
948
   /*if (gds[1] != 255) {
949
      printf ("\n\tCaution: GRIB1 GDS: FOR ALL NWS products, PV should be "
950
              "255 rather than %u\n", gds[1]);
951
   }*/
952
#endif
953
170k
   if ((gds[1] != 255) && (gds[1] > 6)) {
954
      //errSprintf ("GRIB1 GDS: Expect PV = 255 != %d\n", gds[1]);
955
      //return -2;
956
77.6k
   }
957
170k
   gds += 2;
958
170k
   gridType = *(gds++);
959
170k
   switch (gridType) {
960
33.6k
      case GB1S2_LATLON: // Latitude/Longitude Grid
961
35.5k
      case GB1S2_GAUSSIAN_LATLON: // Gaussian Latitude/Longitude
962
55.9k
      case GB1S2_ROTATED: // Rotated Latitude/Longitude
963
55.9k
         if( gridType == GB1S2_ROTATED && (sectLen < 42)) {
964
24
            errSprintf ("For Rotated LatLon GDS, should have at least 42 bytes "
965
24
                        "of data\n");
966
24
            return -1;
967
24
         }
968
55.8k
         if ((sectLen < 32)) {
969
239
            errSprintf ("For LatLon GDS, should have at least 32 bytes "
970
239
                        "of data\n");
971
239
            return -1;
972
239
         }
973
55.6k
         switch(gridType) {
974
1.83k
         case GB1S2_GAUSSIAN_LATLON:
975
1.83k
            gdsMeta->projType = GS3_GAUSSIAN_LATLON;
976
1.83k
            break;
977
20.3k
         case GB1S2_ROTATED:
978
20.3k
            gdsMeta->projType = GS3_ROTATED_LATLON;
979
20.3k
            break;
980
33.4k
         default:
981
33.4k
            gdsMeta->projType = GS3_LATLON;
982
33.4k
            break;
983
55.6k
         }
984
55.6k
         gdsMeta->orientLon = 0;
985
55.6k
         gdsMeta->meshLat = 0;
986
55.6k
         gdsMeta->scaleLat1 = 0;
987
55.6k
         gdsMeta->scaleLat2 = 0;
988
55.6k
         gdsMeta->southLat = 0;
989
55.6k
         gdsMeta->southLon = 0;
990
55.6k
         gdsMeta->center = 0;
991
992
55.6k
         gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
993
55.6k
         if( gdsMeta->Nx == 65535 )
994
39
         {
995
             /* https://rda.ucar.edu/docs/formats/grib/gribdoc/llgrid.html */
996
39
             errSprintf ("Quasi rectangular grid with varying number of grids points per row are not supported\n");
997
39
             return -1;
998
39
         }
999
55.6k
         gds += 2;
1000
55.6k
         gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1001
55.6k
         gds += 2;
1002
55.6k
         gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1003
55.6k
         gds += 3;
1004
55.6k
         gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1005
55.6k
         gds += 3;
1006
1007
55.6k
         gdsMeta->resFlag = *(gds++);
1008
55.6k
         if (gdsMeta->resFlag & 0x40) {
1009
16.7k
            gdsMeta->f_sphere = 0;
1010
16.7k
            gdsMeta->majEarth = 6378.160;
1011
16.7k
            gdsMeta->minEarth = 6356.775;
1012
38.8k
         } else {
1013
38.8k
            gdsMeta->f_sphere = 1;
1014
38.8k
            gdsMeta->majEarth = 6367.47;
1015
38.8k
            gdsMeta->minEarth = 6367.47;
1016
38.8k
         }
1017
1018
55.6k
         gdsMeta->lat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1019
55.6k
         gds += 3;
1020
55.6k
         gdsMeta->lon2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1021
55.6k
         gds += 3;
1022
55.6k
         gdsMeta->Dx = GRIB_UNSIGN_INT2 (*gds, gds[1]) * unit;
1023
55.6k
         gds += 2;
1024
55.6k
         if (gridType == GB1S2_GAUSSIAN_LATLON) {
1025
1.83k
            int np = GRIB_UNSIGN_INT2 (*gds, gds[1]); /* parallels between a pole and the equator */
1026
1.83k
            if( np == 0 )
1027
1.27k
            {
1028
1.27k
                errSprintf ("Invalid Gaussian LatLon\n" );
1029
1.27k
                return -1;
1030
1.27k
            }
1031
557
            gdsMeta->Dy = 90.0 / np;
1032
557
         } else
1033
53.7k
            gdsMeta->Dy = GRIB_UNSIGN_INT2 (*gds, gds[1]) * unit;
1034
54.3k
         gds += 2;
1035
54.3k
         gdsMeta->scan = *gds;
1036
54.3k
         gdsMeta->f_typeLatLon = 0;
1037
#ifdef DEBUG
1038
/*
1039
         printf ("sectLen %ld\n", sectLen);
1040
*/
1041
#endif
1042
54.3k
         if (gridType == GB1S2_ROTATED && sectLen >= 42) {
1043
            /* Check if all 0's or all 1's, which means f_typeLatLon == 0 */
1044
20.3k
            f_allZero = 1;
1045
20.3k
            f_allOne = 1;
1046
223k
            for (i = 0; i < 10; i++) {
1047
203k
               if (gds[i] != 0)
1048
125k
                  f_allZero = 0;
1049
203k
               if (gds[i] != 255)
1050
167k
                  f_allOne = 0;
1051
203k
            }
1052
20.3k
            if (!f_allZero && !f_allOne) {
1053
13.7k
               gdsMeta->f_typeLatLon = 3;
1054
13.7k
               gds += 5;
1055
13.7k
               gdsMeta->southLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1056
13.7k
                                   unit);
1057
13.7k
               gds += 3;
1058
13.7k
               gdsMeta->southLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1059
13.7k
                                   unit);
1060
13.7k
               gds += 3;
1061
13.7k
               MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
1062
13.7k
               gdsMeta->angleRotate = fval_360 (uli_temp);
1063
13.7k
            }
1064
20.3k
         }
1065
#if 0
1066
         else if (gridType == GB1S2_STRETCHED && sectLen >= 42) {
1067
            gds += 5;
1068
            /* Check if all 0's or all 1's, which means f_typeLatLon == 0 */
1069
            f_allZero = 1;
1070
            f_allOne = 1;
1071
            for (i = 0; i < 20; i++) {
1072
               if (gds[i] != 0)
1073
                  f_allZero = 0;
1074
               if (gds[i] != 255)
1075
                  f_allOne = 0;
1076
            }
1077
            if (!f_allZero && !f_allOne) {
1078
               gdsMeta->f_typeLatLon = 1;
1079
               gdsMeta->poleLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1080
                                   unit);
1081
               gds += 3;
1082
               gdsMeta->poleLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1083
                                   unit);
1084
               gds += 3;
1085
               MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
1086
               gdsMeta->stretchFactor = fval_360 (uli_temp);
1087
            }
1088
         else if (gridType == GB1S2_ROTATED_STRETCHED && sectLen >= 52) {
1089
            gds += 5;
1090
            /* Check if all 0's or all 1's, which means f_typeLatLon == 0 */
1091
            f_allZero = 1;
1092
            f_allOne = 1;
1093
            for (i = 0; i < 20; i++) {
1094
               if (gds[i] != 0)
1095
                  f_allZero = 0;
1096
               if (gds[i] != 255)
1097
                  f_allOne = 0;
1098
            }
1099
            if (!f_allZero && !f_allOne) {
1100
               gdsMeta->f_typeLatLon = 2;
1101
               gdsMeta->southLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1102
                                    unit);
1103
               gds += 3;
1104
               gdsMeta->southLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1105
                                    unit);
1106
               gds += 3;
1107
               MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
1108
               gdsMeta->angleRotate = fval_360 (uli_temp);
1109
               gds += 4;
1110
               gdsMeta->poleLat = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1111
                                   unit);
1112
               gds += 3;
1113
               gdsMeta->poleLon = (GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) *
1114
                                   unit);
1115
               gds += 3;
1116
               MEMCPY_BIG (&uli_temp, gds, sizeof (sInt4));
1117
               gdsMeta->stretchFactor = fval_360 (uli_temp);
1118
            }
1119
#endif
1120
1121
54.3k
         break;
1122
1123
25.9k
      case GB1S2_POLAR:
1124
25.9k
         if (sectLen < 32) {
1125
13
            errSprintf ("For Polar GDS, should have 32 bytes of data\n");
1126
13
            return -1;
1127
13
         }
1128
25.9k
         gdsMeta->projType = GS3_POLAR;
1129
25.9k
         gdsMeta->lat2 = 0;
1130
25.9k
         gdsMeta->lon2 = 0;
1131
25.9k
         gdsMeta->southLat = 0;
1132
25.9k
         gdsMeta->southLon = 0;
1133
1134
25.9k
         gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1135
25.9k
         gds += 2;
1136
25.9k
         gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1137
25.9k
         gds += 2;
1138
25.9k
         gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1139
25.9k
         gds += 3;
1140
25.9k
         gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1141
25.9k
         gds += 3;
1142
1143
25.9k
         gdsMeta->resFlag = *(gds++);
1144
25.9k
         if (gdsMeta->resFlag & 0x40) {
1145
4.50k
            gdsMeta->f_sphere = 0;
1146
4.50k
            gdsMeta->majEarth = 6378.160;
1147
4.50k
            gdsMeta->minEarth = 6356.775;
1148
21.4k
         } else {
1149
21.4k
            gdsMeta->f_sphere = 1;
1150
21.4k
            gdsMeta->majEarth = 6367.47;
1151
21.4k
            gdsMeta->minEarth = 6367.47;
1152
21.4k
         }
1153
1154
25.9k
         gdsMeta->orientLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1155
25.9k
         gds += 3;
1156
25.9k
         gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1157
25.9k
         gds += 3;
1158
25.9k
         gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1159
25.9k
         gds += 3;
1160
25.9k
         gdsMeta->meshLat = 60; /* Depends on hemisphere. */
1161
25.9k
         gdsMeta->center = *(gds++);
1162
25.9k
         if (gdsMeta->center & GRIB2BIT_1) {
1163
            /* South polar stereographic. */
1164
6.82k
            gdsMeta->scaleLat1 = gdsMeta->scaleLat2 = -90;
1165
6.82k
            gdsMeta->meshLat = -gdsMeta->meshLat;
1166
19.0k
         } else {
1167
            /* North polar stereographic. */
1168
19.0k
            gdsMeta->scaleLat1 = gdsMeta->scaleLat2 = 90;
1169
19.0k
         }
1170
25.9k
         gdsMeta->scan = *gds;
1171
25.9k
         break;
1172
1173
51.6k
      case GB1S2_LAMBERT:
1174
51.6k
         if (sectLen < 42) {
1175
16
            errSprintf ("For Lambert GDS, should have 42 bytes of data\n");
1176
16
            return -1;
1177
16
         }
1178
51.6k
         gdsMeta->projType = GS3_LAMBERT;
1179
51.6k
         gdsMeta->lat2 = 0;
1180
51.6k
         gdsMeta->lon2 = 0;
1181
1182
51.6k
         gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1183
51.6k
         gds += 2;
1184
51.6k
         gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1185
51.6k
         gds += 2;
1186
51.6k
         gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1187
51.6k
         gds += 3;
1188
51.6k
         gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1189
51.6k
         gds += 3;
1190
1191
51.6k
         gdsMeta->resFlag = *(gds++);
1192
51.6k
         if (gdsMeta->resFlag & 0x40) {
1193
13.7k
            gdsMeta->f_sphere = 0;
1194
13.7k
            gdsMeta->majEarth = 6378.160;
1195
13.7k
            gdsMeta->minEarth = 6356.775;
1196
37.8k
         } else {
1197
37.8k
            gdsMeta->f_sphere = 1;
1198
37.8k
            gdsMeta->majEarth = 6367.47;
1199
37.8k
            gdsMeta->minEarth = 6367.47;
1200
37.8k
         }
1201
1202
51.6k
         gdsMeta->orientLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1203
51.6k
         gds += 3;
1204
51.6k
         gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1205
51.6k
         gds += 3;
1206
51.6k
         gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1207
51.6k
         gds += 3;
1208
51.6k
         gdsMeta->center = *(gds++);
1209
51.6k
         gdsMeta->scan = *(gds++);
1210
51.6k
         gdsMeta->scaleLat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1211
51.6k
         gds += 3;
1212
51.6k
         gdsMeta->scaleLat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1213
51.6k
         gds += 3;
1214
51.6k
         gdsMeta->meshLat = gdsMeta->scaleLat1;
1215
51.6k
         gdsMeta->southLat = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1216
51.6k
         gds += 3;
1217
51.6k
         gdsMeta->southLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1218
51.6k
         break;
1219
1220
36.9k
      case GB1S2_MERCATOR:
1221
36.9k
         if (sectLen < 42) {
1222
133
            errSprintf ("For Mercator GDS, should have 42 bytes of data\n");
1223
133
            return -1;
1224
133
         }
1225
36.8k
         gdsMeta->projType = GS3_MERCATOR;
1226
36.8k
         gdsMeta->southLat = 0;
1227
36.8k
         gdsMeta->southLon = 0;
1228
36.8k
         gdsMeta->orientLon = 0;
1229
36.8k
         gdsMeta->center = 0;
1230
1231
36.8k
         gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1232
36.8k
         gds += 2;
1233
36.8k
         gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]);
1234
36.8k
         gds += 2;
1235
36.8k
         gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1236
36.8k
         gds += 3;
1237
36.8k
         gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1238
36.8k
         gds += 3;
1239
1240
36.8k
         gdsMeta->resFlag = *(gds++);
1241
36.8k
         if (gdsMeta->resFlag & 0x40) {
1242
10.5k
            gdsMeta->f_sphere = 0;
1243
10.5k
            gdsMeta->majEarth = 6378.160;
1244
10.5k
            gdsMeta->minEarth = 6356.775;
1245
26.3k
         } else {
1246
26.3k
            gdsMeta->f_sphere = 1;
1247
26.3k
            gdsMeta->majEarth = 6367.47;
1248
26.3k
            gdsMeta->minEarth = 6367.47;
1249
26.3k
         }
1250
1251
36.8k
         gdsMeta->lat2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1252
36.8k
         gds += 3;
1253
36.8k
         gdsMeta->lon2 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1254
36.8k
         gds += 3;
1255
36.8k
         gdsMeta->scaleLat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) * unit;
1256
36.8k
         gds += 3;
1257
36.8k
         gdsMeta->scaleLat2 = gdsMeta->scaleLat1;
1258
36.8k
         gdsMeta->meshLat = gdsMeta->scaleLat1;
1259
         /* Reserved set to 0. */
1260
36.8k
         gds++;
1261
36.8k
         gdsMeta->scan = *(gds++);
1262
36.8k
         gdsMeta->Dx = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1263
36.8k
         gds += 3;
1264
36.8k
         gdsMeta->Dy = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]);
1265
36.8k
         break;
1266
1267
453
      default:
1268
453
         errSprintf ("Grid projection number is %d\n", gridType);
1269
453
         errSprintf ("Don't know how to handle this grid projection.\n");
1270
453
         return -2;
1271
170k
   }
1272
168k
   gdsMeta->numPts = gdsMeta->Nx * gdsMeta->Ny;
1273
#ifdef DEBUG
1274
/*
1275
printf ("NumPts = %ld\n", gdsMeta->numPts);
1276
printf ("Nx = %ld, Ny = %ld\n", gdsMeta->Nx, gdsMeta->Ny);
1277
*/
1278
#endif
1279
168k
   return 0;
1280
170k
}
1281
1282
/*****************************************************************************
1283
 * ReadGrib1Sect3() --
1284
 *
1285
 * Arthur Taylor / MDL
1286
 *
1287
 * PURPOSE
1288
 *   Parses the GRIB1 "Bit Map Section" or section 3, filling out the bitmap
1289
 * as needed.
1290
 *
1291
 * ARGUMENTS
1292
 *     bms = The compressed part of the message dealing with "BMS". (Input)
1293
 * gribLen = The total length of the GRIB1 message. (Input)
1294
 *  curLoc = Current location in the GRIB1 message. (Output)
1295
 * pBitmap = Pointer to the extracted bitmap. (Output)
1296
 *    NxNy = The total size of the grid. (Input)
1297
 *
1298
 * FILES/DATABASES: None
1299
 *
1300
 * RETURNS: int (could use errSprintf())
1301
 *  0 = OK
1302
 * -1 = gribLen is too small.
1303
 * -2 = unexpected values in bms.
1304
 *
1305
 * HISTORY
1306
 *   4/2003 Arthur Taylor (MDL/RSIS): Created.
1307
 *
1308
 * NOTES
1309
 *****************************************************************************
1310
 */
1311
static int ReadGrib1Sect3 (uChar *bms, uInt4 gribLen, uInt4 *curLoc,
1312
                           uChar **pBitmap, uInt4 NxNy)
1313
35.8k
{
1314
35.8k
   uInt4 sectLen;       /* Length in bytes of the current section. */
1315
35.8k
   short int numeric;   /* Determine if this is a predefined bitmap */
1316
35.8k
   uChar bits;          /* Used to locate which bit we are currently using. */
1317
35.8k
   uInt4 i;             /* Helps traverse the bitmap. */
1318
1319
35.8k
   *pBitmap = nullptr;
1320
1321
35.8k
   uInt4 bmsRemainingSize = gribLen - *curLoc;
1322
35.8k
   if( bmsRemainingSize < 6 )
1323
257
   {
1324
257
      errSprintf ("Ran out of data in BMS (GRIB 1 Section 3)\n");
1325
257
      return -1;
1326
257
   }
1327
35.6k
   sectLen = GRIB_UNSIGN_INT3 (*bms, bms[1], bms[2]);
1328
#ifdef DEBUG
1329
/*
1330
   printf ("Section 3 length = %ld\n", sectLen);
1331
*/
1332
#endif
1333
35.6k
   *curLoc += sectLen;
1334
35.6k
   if (*curLoc > gribLen) {
1335
15.8k
      errSprintf ("Ran out of data in BMS (GRIB 1 Section 3)\n");
1336
15.8k
      return -1;
1337
15.8k
   }
1338
19.7k
   bms += 3;
1339
   /* Assert: *bms currently points to number of unused bits at end of BMS. */
1340
19.7k
   if (NxNy + *bms + 6 * 8 != sectLen * 8) {
1341
4.48k
      errSprintf ("NxNy + # of unused bits != # of available bits\n");
1342
      // commented out to avoid unsigned integer overflow
1343
      // (sInt4) (NxNy + *bms), (sInt4) ((sectLen - 6) * 8));
1344
4.48k
      return -2;
1345
4.48k
   }
1346
15.3k
   bms++;
1347
   /* Assert: Non-zero "numeric" means predefined bitmap. */
1348
15.3k
   numeric = GRIB_UNSIGN_INT2 (*bms, bms[1]);
1349
15.3k
   bms += 2;
1350
15.3k
   if (numeric != 0) {
1351
123
      errSprintf ("Don't handle predefined bitmaps yet.\n");
1352
123
      return -2;
1353
123
   }
1354
15.1k
   bmsRemainingSize -= 6;
1355
15.1k
   if( bmsRemainingSize < (NxNy+7) / 8 )
1356
0
   {
1357
0
      errSprintf ("Ran out of data in BMS (GRIB 1 Section 3)\n");
1358
0
      return -1;
1359
0
   }
1360
15.1k
   *pBitmap = (uChar*) malloc(NxNy);
1361
15.1k
   auto bitmap = *pBitmap;
1362
15.1k
   if( bitmap== nullptr )
1363
0
   {
1364
0
      errSprintf ("Ran out of memory in allocating bitmap (GRIB 1 Section 3)\n");
1365
0
      return -1;
1366
0
   }
1367
15.1k
   bits = 0x80;
1368
21.9M
   for (i = 0; i < NxNy; i++) {
1369
21.9M
      *(bitmap++) = (*bms) & bits;
1370
21.9M
      bits = bits >> 1;
1371
21.9M
      if (bits == 0) {
1372
2.73M
         bms++;
1373
2.73M
         bits = 0x80;
1374
2.73M
      }
1375
21.9M
   }
1376
15.1k
   return 0;
1377
15.1k
}
1378
1379
#ifdef USE_UNPACKCMPLX
1380
static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *curLoc,
1381
                        CPL_UNUSED short int DSF, CPL_UNUSED double *data, CPL_UNUSED grib_MetaData *meta,
1382
                        CPL_UNUSED char f_bms, CPL_UNUSED uChar *bitmap, CPL_UNUSED double unitM,
1383
                        CPL_UNUSED double unitB, CPL_UNUSED short int ESF, CPL_UNUSED double refVal,
1384
                        uChar numBits, uChar f_octet14)
1385
{
1386
   uInt4 secLen;
1387
   int N1;
1388
   int N2;
1389
   int P1;
1390
   int P2;
1391
   uChar octet14;
1392
   uChar f_maxtrixValues;
1393
   uChar f_secBitmap = 0;
1394
   uChar f_secValDiffWid;
1395
   int i;
1396
   uInt4 uli_temp;      /* Used to store sInt4s (temporarily) */
1397
   uChar bufLoc;        /* Keeps track of where to start getting more data
1398
                         * out of the packed data stream. */
1399
   size_t numUsed;      /* How many bytes were used in a given call to
1400
                         * memBitRead. */
1401
   uChar *width;
1402
1403
   secLen = 11;
1404
   N1 = GRIB_UNSIGN_INT2 (bds[0], bds[1]);
1405
   octet14 = bds[2];
1406
   printf ("octet14, %d\n", octet14);
1407
   if (f_octet14) {
1408
      f_maxtrixValues = octet14 & GRIB2BIT_2;
1409
      f_secBitmap = octet14 & GRIB2BIT_3;
1410
      f_secValDiffWid = octet14 & GRIB2BIT_4;
1411
      printf ("f_matrixValues, f_secBitmap, f_secValeDiffWid %d %d %d\n",
1412
              f_maxtrixValues, f_secBitmap, f_secValDiffWid);
1413
   }
1414
   N2 = GRIB_UNSIGN_INT2 (bds[3], bds[4]);
1415
   P1 = GRIB_UNSIGN_INT2 (bds[5], bds[6]);
1416
   P2 = GRIB_UNSIGN_INT2 (bds[7], bds[8]);
1417
   printf ("N1 N2 P1 P2 : %d %d %d %d\n", N1, N2, P1, P2);
1418
   printf ("Reserved %u\n", bds[9]);
1419
   bds += 10;
1420
   secLen += 10;
1421
1422
   width = (uChar *) malloc (P1 * sizeof (uChar));
1423
1424
   for (i = 0; i < P1; i++) {
1425
      width[i] = *bds;
1426
      printf ("(Width %d %u)\n", i, width[i]);
1427
      bds++;
1428
      secLen++;
1429
   }
1430
   if (f_secBitmap) {
1431
      bufLoc = 8;
1432
      for (i = 0; i < P2; i++) {
1433
         memBitRead (&uli_temp, sizeof (sInt4), bds, 1, &bufLoc, &numUsed);
1434
         printf ("(%d %u) ", i, uli_temp);
1435
         if (numUsed != 0) {
1436
            printf ("\n");
1437
            bds += numUsed;
1438
            secLen++;
1439
         }
1440
      }
1441
      if (bufLoc != 8) {
1442
         bds++;
1443
         secLen++;
1444
      }
1445
      printf ("Observed Sec Len %u\n", secLen);
1446
   } else {
1447
      /* Jump over widths and secondary bitmap */
1448
      bds += (N1 - 21);
1449
      secLen += (N1 - 21);
1450
   }
1451
1452
   bufLoc = 8;
1453
   for (i = 0; i < P1; i++) {
1454
      memBitRead (&uli_temp, sizeof (sInt4), bds, numBits, &bufLoc, &numUsed);
1455
      printf ("(%d %u) (numUsed %ld numBits %d)", i, uli_temp,
1456
              (long) numUsed, numBits);
1457
      if (numUsed != 0) {
1458
         printf ("\n");
1459
         bds += numUsed;
1460
         secLen++;
1461
      }
1462
   }
1463
   if (bufLoc != 8) {
1464
      // cppcheck-suppress uselessAssignmentPtrArg
1465
      bds++;
1466
      secLen++;
1467
   }
1468
1469
   printf ("Observed Sec Len %u\n", secLen);
1470
   printf ("N2 = %d\n", N2);
1471
1472
   errSprintf ("Don't know how to handle Complex GRIB1 packing yet.\n");
1473
   free (width);
1474
   return -2;
1475
1476
}
1477
#endif /* USE_UNPACKCMPLX */
1478
1479
/*****************************************************************************
1480
 * ReadGrib1Sect4() --
1481
 *
1482
 * Arthur Taylor / MDL
1483
 *
1484
 * PURPOSE
1485
 *   Unpacks the "Binary Data Section" or section 4.
1486
 *
1487
 * ARGUMENTS
1488
 *     bds = The compressed part of the message dealing with "BDS". (Input)
1489
 * gribLen = The total length of the GRIB1 message. (Input)
1490
 *  curLoc = Current location in the GRIB1 message. (Input/Output)
1491
 *     DSF = Decimal Scale Factor for unpacking the data. (Input)
1492
 *    data = The extracted grid. (Output)
1493
 *    meta = The meta data associated with the grid (Input/Output)
1494
 *   f_bms = True if bitmap is to be used. (Input)
1495
 *  bitmap = 0 if missing data, 1 if valid data. (Input)
1496
 *   unitM = The M unit conversion value in equation y = Mx + B. (Input)
1497
 *   unitB = The B unit conversion value in equation y = Mx + B. (Input)
1498
 *
1499
 * FILES/DATABASES: None
1500
 *
1501
 * RETURNS: int (could use errSprintf())
1502
 *  0 = OK
1503
 * -1 = gribLen is too small.
1504
 * -2 = unexpected values in bds.
1505
 *
1506
 * HISTORY
1507
 *   4/2003 Arthur Taylor (MDL/RSIS): Created
1508
 *   3/2004 AAT: Switched {# Pts * (# Bits in a Group) +
1509
 *          # of unused bits != # of available bits} to a warning from an
1510
 *          error.
1511
 *
1512
 * NOTES
1513
 * 1) See metaparse.c : ParseGrid()
1514
 * 2) Currently, only handles "Simple pack".
1515
 *****************************************************************************
1516
 */
1517
static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
1518
                           short int DSF, double *data, grib_MetaData *meta,
1519
                           char f_bms, uChar *bitmap, double unitM,
1520
                           double unitB)
1521
146k
{
1522
146k
   uInt4 sectLen;       /* Length in bytes of the current section. */
1523
146k
   short int ESF;       /* Power of 2 scaling factor. */
1524
146k
   uInt4 uli_temp;      /* Used to store sInt4s (temporarily) */
1525
146k
   double refVal;       /* The reference value for the grid, also the minimum
1526
                         * value. */
1527
146k
   uChar numBits;       /* # of bits for a single element of data. */
1528
146k
   uChar numUnusedBit;  /* # of extra bits at end of record. */
1529
146k
   uChar f_spherHarm;   /* Flag if data contains Spherical Harmonics. */
1530
146k
   uChar f_cmplxPack;   /* Flag if complex packing was used. */
1531
#ifdef USE_UNPACKCMPLX
1532
   uChar f_octet14;     /* Flag if octet 14 was used. */
1533
#endif
1534
146k
   uChar bufLoc;        /* Keeps track of where to start getting more data
1535
                         * out of the packed data stream. */
1536
146k
   uChar f_convert;     /* Determine if scan mode implies that we have to do
1537
                         * manipulation as we read the grid to get desired
1538
                         * internal scan mode. */
1539
146k
   uInt4 i;             /* Used to traverse the grid. */
1540
146k
   size_t numUsed;      /* How many bytes were used in a given call to
1541
                         * memBitRead. */
1542
146k
   double d_temp;       /* Holds the extracted data until we put it in data */
1543
146k
   sInt4 newIndex;      /* Where to put the answer (primarily if f_convert) */
1544
146k
   sInt4 x;             /* Used to help compute newIndex , if f_convert. */
1545
146k
   sInt4 y;             /* Used to help compute newIndex , if f_convert. */
1546
146k
   double resetPrim;    /* If possible, used to reset the primary missing
1547
                         * value from 9.999e20 to a reasonable # (9999) */
1548
1549
146k
   if (meta->gds.Nx * meta->gds.Ny != meta->gds.numPts) {
1550
0
      errSprintf ("(Nx * Ny != numPts) ?? in BDS (GRIB 1 Section 4)\n");
1551
0
      return -2;
1552
0
   }
1553
146k
   if( *curLoc >= gribLen )
1554
20.0k
       return -1;
1555
1556
126k
   uInt4 bdsRemainingSize = gribLen - *curLoc;
1557
126k
   if( bdsRemainingSize < 3 )
1558
10.1k
       return -1;
1559
1560
116k
   sectLen = GRIB_UNSIGN_INT3 (*bds, bds[1], bds[2]);
1561
#ifdef DEBUG
1562
/*
1563
   printf ("Section 4 length = %ld\n", sectLen);
1564
*/
1565
#endif
1566
116k
   *curLoc += sectLen;
1567
116k
   if (*curLoc > gribLen) {
1568
55.9k
      errSprintf ("Ran out of data in BDS (GRIB 1 Section 4)\n");
1569
55.9k
      return -1;
1570
55.9k
   }
1571
60.8k
   bds += 3;
1572
60.8k
   bdsRemainingSize -= 3;
1573
1574
   /* Assert: bds now points to the main pack flag. */
1575
60.8k
   if( bdsRemainingSize < 1 )
1576
172
       return -1;
1577
60.6k
   f_spherHarm = (*bds) & GRIB2BIT_1;
1578
60.6k
   f_cmplxPack = (*bds) & GRIB2BIT_2;
1579
60.6k
   meta->gridAttrib.fieldType = (*bds) & GRIB2BIT_3;
1580
#ifdef USE_UNPACKCMPLX
1581
   f_octet14 = (*bds) & GRIB2BIT_4;
1582
#endif
1583
1584
60.6k
   numUnusedBit = (*bds) & 0x0f;
1585
#ifdef DEBUG
1586
/*
1587
   printf ("bds byte flag = %d\n", *bds);
1588
   printf ("Number of unused bits = %d\n", numUnusedBit);
1589
*/
1590
#endif
1591
60.6k
   if (f_spherHarm) {
1592
400
      errSprintf ("Don't know how to handle Spherical Harmonics yet.\n");
1593
400
      return -2;
1594
400
   }
1595
/*
1596
   if (f_octet14) {
1597
      errSprintf ("Don't know how to handle Octet 14 data yet.\n");
1598
      errSprintf ("bds byte flag = %d\n", *bds);
1599
      errSprintf ("bds byte: %d %d %d %d\n", f_spherHarm, f_cmplxPack,
1600
                  meta->gridAttrib.fieldType, f_octet14);
1601
      return -2;
1602
   }
1603
*/
1604
60.2k
   if (f_cmplxPack) {
1605
9.27k
      meta->gridAttrib.packType = 2;
1606
50.9k
   } else {
1607
50.9k
      meta->gridAttrib.packType = 0;
1608
50.9k
   }
1609
60.2k
   bds++;
1610
60.2k
   bdsRemainingSize --;
1611
1612
   /* Assert: bds now points to E (power of 2 scaling factor). */
1613
60.2k
   if( bdsRemainingSize < 2 )
1614
38
       return -1;
1615
60.2k
   ESF = GRIB_SIGN_INT2 (*bds, bds[1]);
1616
60.2k
   bds += 2;
1617
60.2k
   bdsRemainingSize -= 2;
1618
1619
60.2k
   if( bdsRemainingSize < 4 )
1620
1.93k
       return -1;
1621
58.2k
   MEMCPY_BIG (&uli_temp, bds, sizeof (sInt4));
1622
58.2k
   refVal = fval_360 (uli_temp);
1623
58.2k
   bds += 4;
1624
58.2k
   bdsRemainingSize -= 4;
1625
1626
   /* Assert: bds is now the number of bits in a group. */
1627
58.2k
   if( bdsRemainingSize < 1 )
1628
108
       return -1;
1629
58.1k
   numBits = *bds;
1630
/*
1631
#ifdef DEBUG
1632
   printf ("refValue %f numBits %d\n", refVal, numBits);
1633
   printf ("ESF %d DSF %d\n", ESF, DSF);
1634
#endif
1635
*/
1636
58.1k
   if (f_cmplxPack) {
1637
#ifdef USE_UNPACKCMPLX
1638
      bds++;
1639
      bdsRemainingSize --;
1640
      return UnpackCmplx (bds, gribLen, curLoc, DSF, data, meta, f_bms,
1641
                          bitmap, unitM, unitB, ESF, refVal, numBits,
1642
                          f_octet14);
1643
#else
1644
9.27k
      errSprintf ("Don't know how to handle Complex GRIB1 packing yet.\n");
1645
9.27k
      return -2;
1646
9.27k
#endif
1647
9.27k
   }
1648
1649
48.8k
   if (!f_bms && (
1650
36.4k
       sectLen < 11 ||
1651
36.4k
       (numBits > 0 && meta->gds.numPts > UINT_MAX / numBits) ||
1652
36.4k
       (meta->gds.numPts * numBits > UINT_MAX - numUnusedBit))) {
1653
26.2k
     printf ("numPts * (numBits in a Group) + # of unused bits != "
1654
26.2k
              "# of available bits\n");
1655
26.2k
   }
1656
22.6k
   else if (!f_bms &&
1657
22.6k
            (meta->gds.numPts * numBits + numUnusedBit) != (sectLen - 11) * 8) {
1658
4.94k
      printf ("numPts * (numBits in a Group) + # of unused bits %d != "
1659
4.94k
              "# of available bits %d\n",
1660
4.94k
              (sInt4) (meta->gds.numPts * numBits + numUnusedBit),
1661
4.94k
              (sInt4) ((sectLen - 11) * 8));
1662
/*
1663
      errSprintf ("numPts * (numBits in a Group) + # of unused bits %ld != "
1664
                  "# of available bits %ld\n",
1665
                  (sInt4) (meta->gds.numPts * numBits + numUnusedBit),
1666
                  (sInt4) ((sectLen - 11) * 8));
1667
      return -2;
1668
*/
1669
4.94k
   }
1670
48.8k
   if (numBits > 32) {
1671
7.59k
      errSprintf ("The number of bits per number is larger than 32?\n");
1672
7.59k
      return -2;
1673
7.59k
   }
1674
41.2k
   bds++;
1675
41.2k
   bdsRemainingSize -= 1;
1676
1677
   /* Convert Units. */
1678
41.2k
   {
1679
41.2k
   double pow_10_DSF = pow (10.0, DSF);
1680
41.2k
   if( pow_10_DSF == 0.0 ) {
1681
143
      errSprintf ("pow_10_DSF == 0.0\n");
1682
143
      return -2;
1683
143
   }
1684
41.1k
   if (unitM == -10) {
1685
0
      meta->gridAttrib.min = pow (10.0, (refVal * pow (2.0, ESF) /
1686
0
                                       pow_10_DSF));
1687
41.1k
   } else {
1688
/*      meta->gridAttrib.min = unitM * (refVal / pow (10.0, DSF)) + unitB; */
1689
41.1k
      meta->gridAttrib.min = unitM * (refVal * pow (2.0, ESF) /
1690
41.1k
                                      pow_10_DSF) + unitB;
1691
41.1k
   }
1692
41.1k
   }
1693
1694
0
   meta->gridAttrib.max = meta->gridAttrib.min;
1695
41.1k
   meta->gridAttrib.f_maxmin = 1;
1696
41.1k
   meta->gridAttrib.numMiss = 0;
1697
41.1k
   if (refVal >= std::numeric_limits<float>::max() || std::isnan(refVal)) {
1698
1.50k
      meta->gridAttrib.refVal = std::numeric_limits<float>::max();
1699
39.6k
   } else if (refVal <= -std::numeric_limits<float>::max()) {
1700
1.80k
      meta->gridAttrib.refVal = -std::numeric_limits<float>::max();
1701
37.8k
   } else {
1702
37.8k
      meta->gridAttrib.refVal = static_cast<float>(refVal);
1703
37.8k
   }
1704
41.1k
   meta->gridAttrib.ESF = ESF;
1705
41.1k
   meta->gridAttrib.DSF = DSF;
1706
41.1k
   bufLoc = 8;
1707
   /* Internally we use scan = 0100.  Scan is usually 0100 but if need be, we
1708
    * can convert it. */
1709
41.1k
   f_convert = ((meta->gds.scan & 0xe0) != 0x40);
1710
1711
41.1k
   if (f_bms) {
1712
12.3k
      meta->gridAttrib.f_miss = 1;
1713
12.3k
      meta->gridAttrib.missPri = UNDEFINED;
1714
12.3k
   }
1715
28.8k
   else
1716
28.8k
   {
1717
28.8k
      meta->gridAttrib.f_miss = 0;
1718
28.8k
   }
1719
1720
41.1k
   if (f_bms) {
1721
/*
1722
#ifdef DEBUG
1723
      printf ("There is a bitmap?\n");
1724
#endif
1725
*/
1726
      /* Start unpacking the data, assuming there is a bitmap. */
1727
12.8M
      for (i = 0; i < meta->gds.numPts; i++) {
1728
         /* Find the destination index. */
1729
12.8M
         if (f_convert) {
1730
            /* ScanIndex2XY returns value as if scan was 0100 */
1731
5.09M
            ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
1732
5.09M
                          meta->gds.Ny);
1733
5.09M
            newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
1734
7.76M
         } else {
1735
7.76M
            newIndex = i;
1736
7.76M
         }
1737
         /* A 0 in bitmap means no data. A 1 in bitmap means data. */
1738
         // cppcheck-suppress nullPointer
1739
12.8M
         if (!bitmap[i]) {
1740
4.64M
            meta->gridAttrib.numMiss++;
1741
4.64M
            if( data ) data[newIndex] = UNDEFINED;
1742
8.21M
         } else {
1743
8.21M
            if (numBits != 0) {
1744
8.03M
                if( ((int)bdsRemainingSize - 1) * 8 + bufLoc < (int)numBits )
1745
86
                    return -1;
1746
8.03M
               memBitRead (&uli_temp, sizeof (sInt4), bds, numBits,
1747
8.03M
                           &bufLoc, &numUsed);
1748
8.03M
               assert( numUsed <= bdsRemainingSize );
1749
8.03M
               bds += numUsed;
1750
8.03M
               bdsRemainingSize -= (uInt4)numUsed;
1751
8.03M
               d_temp = (refVal + (uli_temp * pow (2.0, ESF))) / pow (10.0, DSF);
1752
               /* Convert Units. */
1753
8.03M
               if (unitM == -10) {
1754
0
                  d_temp = pow (10.0, d_temp);
1755
8.03M
               } else {
1756
8.03M
                  d_temp = unitM * d_temp + unitB;
1757
8.03M
               }
1758
8.03M
               if (meta->gridAttrib.max < d_temp) {
1759
166k
                  meta->gridAttrib.max = d_temp;
1760
166k
               }
1761
8.03M
               if( data ) data[newIndex] = d_temp;
1762
8.03M
            } else {
1763
               /* Assert: d_temp = unitM * refVal / pow (10.0,DSF) + unitB. */
1764
               /* Assert: min = unitM * refVal / pow (10.0, DSF) + unitB. */
1765
178k
               if( data ) data[newIndex] = meta->gridAttrib.min;
1766
178k
            }
1767
8.21M
         }
1768
12.8M
      }
1769
      /* Reset the missing value to UNDEFINED_PRIM if possible.  If not
1770
       * possible, make sure UNDEFINED is outside the range.  If UNDEFINED
1771
       * is_ in the range, choose max + 1 for missing. */
1772
12.2k
      resetPrim = 0;
1773
12.2k
      if ((meta->gridAttrib.max < UNDEFINED_PRIM) ||
1774
12.2k
          (meta->gridAttrib.min > UNDEFINED_PRIM)) {
1775
12.0k
         resetPrim = UNDEFINED_PRIM;
1776
12.0k
      } else if ((meta->gridAttrib.max >= UNDEFINED) &&
1777
207
                 (meta->gridAttrib.min <= UNDEFINED)) {
1778
19
         resetPrim = meta->gridAttrib.max + 1;
1779
19
      }
1780
12.2k
      if (resetPrim != 0) {
1781
12.0k
         meta->gridAttrib.missPri = resetPrim;
1782
12.0k
      }
1783
12.2k
      if (data != nullptr && resetPrim != 0) {
1784
4.09M
         for (i = 0; i < meta->gds.numPts; i++) {
1785
            /* Find the destination index. */
1786
4.09M
            if (f_convert) {
1787
               /* ScanIndex2XY returns value as if scan was 0100 */
1788
1.69M
               ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
1789
1.69M
                             meta->gds.Ny);
1790
1.69M
               newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
1791
2.40M
            } else {
1792
2.40M
               newIndex = i;
1793
2.40M
            }
1794
            // cppcheck-suppress nullPointer
1795
4.09M
            if (!bitmap[i]) {
1796
1.41M
               data[newIndex] = resetPrim;
1797
1.41M
            }
1798
4.09M
         }
1799
4.04k
      }
1800
1801
28.8k
   } else {
1802
1803
28.8k
      if( !data )
1804
19.6k
        return 0;
1805
1806
#ifdef DEBUG
1807
/*
1808
      printf ("There is no bitmap?\n");
1809
*/
1810
#endif
1811
1812
      /* Start unpacking the data, assuming there is NO bitmap. */
1813
1.72G
      for (i = 0; i < meta->gds.numPts; i++) {
1814
1.72G
         if (numBits != 0) {
1815
            /* Find the destination index. */
1816
1.16M
            if (f_convert) {
1817
               /* ScanIndex2XY returns value as if scan was 0100 */
1818
1.16M
               ScanIndex2XY (i, &x, &y, meta->gds.scan, meta->gds.Nx,
1819
1.16M
                             meta->gds.Ny);
1820
1.16M
               newIndex = (x - 1) + (y - 1) * meta->gds.Nx;
1821
1.16M
            } else {
1822
2.48k
               newIndex = i;
1823
2.48k
            }
1824
1825
1.16M
            if( ((int)bdsRemainingSize - 1) * 8 + bufLoc < (int)numBits )
1826
3.13k
                return -1;
1827
1.16M
            memBitRead (&uli_temp, sizeof (sInt4), bds, numBits, &bufLoc,
1828
1.16M
                        &numUsed);
1829
1.16M
            assert( numUsed <= bdsRemainingSize );
1830
1.16M
            bds += numUsed;
1831
1.16M
            bdsRemainingSize -= (uInt4)numUsed;
1832
1.16M
            d_temp = (refVal + (uli_temp * pow (2.0, ESF))) / pow (10.0, DSF);
1833
1834
#ifdef DEBUG
1835
/*
1836
            if (i == 1) {
1837
               printf ("refVal %f, uli_temp %ld, ans %f\n", refVal, uli_temp,
1838
                       d_temp);
1839
               printf ("numBits %d, bufLoc %d, numUsed %d\n", numBits,
1840
                       bufLoc, numUsed);
1841
            }
1842
*/
1843
#endif
1844
1845
            /* Convert Units. */
1846
1.16M
            if (unitM == -10) {
1847
0
               d_temp = pow (10.0, d_temp);
1848
1.16M
            } else {
1849
1.16M
               d_temp = unitM * d_temp + unitB;
1850
1.16M
            }
1851
1.16M
            if (meta->gridAttrib.max < d_temp) {
1852
43.8k
               meta->gridAttrib.max = d_temp;
1853
43.8k
            }
1854
1.16M
            data[newIndex] = d_temp;
1855
1.72G
         } else {
1856
            /* Assert: whole array = unitM * refVal + unitB. */
1857
            /* Assert: *min = unitM * refVal + unitB. */
1858
1.72G
            data[i] = meta->gridAttrib.min;
1859
1.72G
         }
1860
1.72G
      }
1861
9.15k
   }
1862
18.2k
   return 0;
1863
41.1k
}
1864
1865
/*****************************************************************************
1866
 * ReadGrib1Record() --
1867
 *
1868
 * Arthur Taylor / MDL
1869
 *
1870
 * PURPOSE
1871
 *   Reads in a GRIB1 message, and parses the data into various data
1872
 * structures, for use with other code.
1873
 *
1874
 * ARGUMENTS
1875
 *           fp = An opened GRIB2 file already at the correct message. (Input)
1876
 *       f_unit = 0 use GRIB2 units, 1 use English, 2 use metric. (Input)
1877
 *    Grib_Data = The read in GRIB2 grid. (Output)
1878
 * grib_DataLen = Size of Grib_Data. (Output)
1879
 *         meta = A filled in meta structure (Output)
1880
 *           IS = The structure containing all the arrays that the
1881
 *                unpacker uses (Output)
1882
 *        sect0 = Already read in section 0 data. (Input)
1883
 *      gribLen = Length of the GRIB1 message. (Input)
1884
 *     majEarth = Used to override the GRIB major axis of earth. (Input)
1885
 *     minEarth = Used to override the GRIB minor axis of earth. (Input)
1886
 *
1887
 * FILES/DATABASES:
1888
 *   An already opened file pointing to the desired GRIB1 message.
1889
 *
1890
 * RETURNS: int (could use errSprintf())
1891
 *  0 = OK
1892
 * -1 = Problems reading in the PDS.
1893
 * -2 = Problems reading in the GDS.
1894
 * -3 = Problems reading in the BMS.
1895
 * -4 = Problems reading in the BDS.
1896
 * -5 = Problems reading the closing section.
1897
 *
1898
 * HISTORY
1899
 *   4/2003 Arthur Taylor (MDL/RSIS): Created
1900
 *   5/2003 AAT: Was not updating offset.  It should be updated by
1901
 *               calling routine anyways, so I got rid of the parameter.
1902
 *   7/2003 AAT: Allowed user to override the radius of earth.
1903
 *   8/2003 AAT: Found a memory Leak (Had been setting unitName to NULL).
1904
 *   2/2004 AAT: Added maj/min earth override.
1905
 *   3/2004 AAT: Added ability to change units.
1906
 *
1907
 * NOTES
1908
 * 1) Could also compare GDS with the one specified by gridID
1909
 * 2) Could add gridID support.
1910
 * 3) Should add unitM / unitB support.
1911
 *****************************************************************************
1912
 */
1913
int ReadGrib1Record (VSILFILE *fp, sChar f_unit, double **Grib_Data,
1914
                     uInt4 *grib_DataLen, grib_MetaData *meta,
1915
                     IS_dataType *IS, sInt4 sect0[SECT0LEN_WORD],
1916
                     uInt4 gribLen, double majEarth, double minEarth)
1917
179k
{
1918
179k
   sInt4 nd5;           /* Size of grib message rounded up to the nearest *
1919
                         * sInt4. */
1920
179k
   uChar *c_ipack;      /* A char ptr to the message stored in IS->ipack */
1921
179k
   uInt4 curLoc;        /* Current location in the GRIB message. */
1922
179k
   char f_gds;          /* flag if there is a gds section. */
1923
179k
   char f_bms;          /* flag if there is a bms section. */
1924
179k
   double *grib_Data = nullptr;   /* A pointer to Grib_Data for ease of manipulation. */
1925
179k
   uChar *bitmap = nullptr; /* A char field (0=noData, 1=data) set up in BMS. */
1926
179k
   short int DSF;       /* Decimal Scale Factor for unpacking the data. */
1927
179k
   double unitM = 1;    /* M in y = Mx + B, for unit conversion. */
1928
179k
   double unitB = 0;    /* B in y = Mx + B, for unit conversion. */
1929
179k
   uChar gridID;        /* Which GDS specs to use. */
1930
179k
   const char *varName; /* The name of the data stored in the grid. */
1931
179k
   const char *varComment; /* Extra comments about the data stored in grid. */
1932
179k
   const char *varUnit; /* Holds the name of the unit [K] [%] .. etc */
1933
179k
   sInt4 li_temp;       /* Used to make sure section 5 is 7777. */
1934
179k
   char unitName[15];   /* Holds the string name of the current unit. */
1935
179k
   int unitLen;         /* String length of string name of current unit. */
1936
1937
   /* Make room for entire message, and read it in. */
1938
   /* nd5 needs to be gribLen in (sInt4) units rounded up. */
1939
179k
   nd5 = (gribLen + 3) / 4;
1940
179k
   if (nd5 > IS->ipackLen) {
1941
179k
      if( gribLen > 100 * 1024 * 1024 )
1942
0
      {
1943
0
         vsi_l_offset curPos = VSIFTellL(fp);
1944
0
         VSIFSeekL(fp, 0, SEEK_END);
1945
0
         vsi_l_offset fileSize = VSIFTellL(fp);
1946
0
         VSIFSeekL(fp, curPos, SEEK_SET);
1947
0
         if( fileSize < gribLen )
1948
0
         {
1949
0
            errSprintf("File too short");
1950
0
            return -1;
1951
0
         }
1952
0
      }
1953
179k
      sInt4* newipack = (sInt4 *) realloc ((void *) (IS->ipack),
1954
179k
                                     nd5 * sizeof (sInt4));
1955
179k
      if( newipack == nullptr )
1956
0
      {
1957
0
          errSprintf ("Out of memory\n");
1958
0
          return -1;
1959
0
      }
1960
179k
      IS->ipackLen = nd5;
1961
179k
      IS->ipack = newipack;
1962
179k
   }
1963
179k
   c_ipack = reinterpret_cast<uChar *>(IS->ipack);
1964
   /* Init last sInt4 to 0, to make sure that the padded bytes are 0. */
1965
179k
   IS->ipack[nd5 - 1] = 0;
1966
   /* Init first 2 sInt4 to sect0. */
1967
179k
   memcpy (c_ipack, sect0, SECT0LEN_WORD * 2);
1968
   /* Read in the rest of the message. */
1969
179k
   if (VSIFReadL (c_ipack + SECT0LEN_WORD * 2, sizeof (char),
1970
179k
              (gribLen - SECT0LEN_WORD * 2), fp) + SECT0LEN_WORD * 2 != gribLen) {
1971
658
      errSprintf ("Ran out of file\n");
1972
658
      return -1;
1973
658
   }
1974
1975
   /* Preceding was in degrib2, next part is specific to GRIB1. */
1976
178k
   curLoc = 8;
1977
178k
   if (ReadGrib1Sect1 (c_ipack + curLoc, gribLen - curLoc, gribLen, &curLoc, &(meta->pds1),
1978
178k
                       &f_gds, &gridID, &f_bms, &DSF, &(meta->center),
1979
178k
                       &(meta->subcenter)) != 0) {
1980
0
      preErrSprintf ("Inside ReadGrib1Record\n");
1981
0
      return -1;
1982
0
   }
1983
1984
   /* Get the Grid Definition Section. */
1985
178k
   if (f_gds) {
1986
176k
      if (ReadGrib1Sect2 (c_ipack + curLoc, gribLen, &curLoc,
1987
176k
                          &(meta->gds)) != 0) {
1988
8.10k
         preErrSprintf ("Inside ReadGrib1Record\n");
1989
8.10k
         return -2;
1990
8.10k
      }
1991
      /* Could also compare GDS with the one specified by gridID? */
1992
176k
   } else {
1993
1.82k
      errSprintf ("Don't know how to handle a gridID lookup yet.\n");
1994
1.82k
      return -2;
1995
1.82k
   }
1996
168k
   meta->pds1.gridID = gridID;
1997
   /* Allow data originating from NCEP to be 6371.2 by default. */
1998
168k
   if (meta->center == NMC) {
1999
77.2k
      if (meta->gds.majEarth == 6367.47) {
2000
63.3k
         meta->gds.f_sphere = 1;
2001
63.3k
         meta->gds.majEarth = 6371.2;
2002
63.3k
         meta->gds.minEarth = 6371.2;
2003
63.3k
      }
2004
77.2k
   }
2005
168k
   if ((majEarth > 6300) && (majEarth < 6400)) {
2006
0
      if ((minEarth > 6300) && (minEarth < 6400)) {
2007
0
         meta->gds.f_sphere = 0;
2008
0
         meta->gds.majEarth = majEarth;
2009
0
         meta->gds.minEarth = minEarth;
2010
0
         if (majEarth == minEarth) {
2011
0
            meta->gds.f_sphere = 1;
2012
0
         }
2013
0
      } else {
2014
0
         meta->gds.f_sphere = 1;
2015
0
         meta->gds.majEarth = majEarth;
2016
0
         meta->gds.minEarth = majEarth;
2017
0
      }
2018
0
   }
2019
2020
168k
   if( Grib_Data )
2021
45.5k
   {
2022
     /* Allocate memory for the grid. */
2023
45.5k
     if (meta->gds.numPts > *grib_DataLen) {
2024
45.5k
      if( meta->gds.numPts > 100 * 1024 * 1024 )
2025
1.06k
      {
2026
1.06k
          vsi_l_offset curPos = VSIFTellL(fp);
2027
1.06k
          VSIFSeekL(fp, 0, SEEK_END);
2028
1.06k
          vsi_l_offset fileSize = VSIFTellL(fp);
2029
1.06k
          VSIFSeekL(fp, curPos, SEEK_SET);
2030
          // allow a compression ratio of 1:1000
2031
1.06k
          if( meta->gds.numPts / 1000 > (uInt4)fileSize )
2032
1.04k
          {
2033
1.04k
            errSprintf ("ERROR: File too short\n");
2034
1.04k
            *grib_DataLen = 0;
2035
1.04k
            *Grib_Data = nullptr;
2036
1.04k
            return -2;
2037
1.04k
          }
2038
1.06k
      }
2039
2040
44.4k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
2041
44.4k
      if( meta->gds.numPts > static_cast<size_t>(INT_MAX) /  sizeof (double) )
2042
9
      {
2043
9
          errSprintf ("Memory allocation failed due to being bigger than 2 GB in fuzzing mode");
2044
9
          *grib_DataLen = 0;
2045
9
          *Grib_Data = nullptr;
2046
9
          return -2;
2047
9
      }
2048
44.4k
#endif
2049
2050
44.4k
      *grib_DataLen = meta->gds.numPts;
2051
44.4k
      *Grib_Data = (double *) realloc ((void *) (*Grib_Data),
2052
44.4k
                                       (*grib_DataLen) * sizeof (double));
2053
44.4k
      if (!(*Grib_Data))
2054
0
      {
2055
0
        *grib_DataLen = 0;
2056
0
        return -1;
2057
0
      }
2058
44.4k
     }
2059
44.5k
     grib_Data = *Grib_Data;
2060
44.5k
   }
2061
2062
   /* Get the Bit Map Section. */
2063
167k
   if (f_bms) {
2064
35.8k
      if (ReadGrib1Sect3 (c_ipack + curLoc, gribLen, &curLoc, &bitmap,
2065
35.8k
                          meta->gds.numPts) != 0) {
2066
20.6k
         free (bitmap);
2067
20.6k
         preErrSprintf ("Inside ReadGrib1Record\n");
2068
20.6k
         return -3;
2069
20.6k
      }
2070
35.8k
   }
2071
2072
   /* Figure out some basic stuff about the grid. */
2073
   /* Following is similar to metaparse.c : ParseElemName */
2074
146k
   GRIB1_Table2LookUp (&(meta->pds1), &varName, &varComment, &varUnit,
2075
146k
                       &(meta->convert), meta->center, meta->subcenter);
2076
146k
   meta->element = (char *) realloc ((void *) (meta->element),
2077
146k
                                     (1 + strlen (varName)) * sizeof (char));
2078
146k
   strcpy (meta->element, varName);
2079
146k
   meta->unitName = (char *) realloc ((void *) (meta->unitName),
2080
146k
                                      (1 + 2 + strlen (varUnit)) *
2081
146k
                                      sizeof (char));
2082
146k
   snprintf (meta->unitName,
2083
146k
            (1 + 2 + strlen (varUnit)) *
2084
146k
                                      sizeof (char),
2085
146k
            "[%s]", varUnit);
2086
146k
   meta->comment = (char *) realloc ((void *) (meta->comment),
2087
146k
                                     (1 + strlen (varComment) +
2088
146k
                                      strlen (varUnit)
2089
146k
                                      + 2 + 1) * sizeof (char));
2090
146k
   snprintf (meta->comment,
2091
146k
            (1 + strlen (varComment) +
2092
146k
                                      strlen (varUnit)
2093
146k
                                      + 2 + 1) * sizeof (char),
2094
146k
            "%s [%s]", varComment, varUnit);
2095
2096
146k
   if (ComputeUnit (meta->convert, meta->unitName, f_unit, &unitM, &unitB,
2097
146k
                    unitName) == 0) {
2098
1.83k
      unitLen = static_cast<int>(strlen (unitName));
2099
1.83k
      meta->unitName = (char *) realloc ((void *) (meta->unitName),
2100
1.83k
                                         1 + unitLen * sizeof (char));
2101
1.83k
      memcpy (meta->unitName, unitName, unitLen);
2102
1.83k
      meta->unitName[unitLen] = '\0';
2103
1.83k
   }
2104
2105
   /* Read the GRID. */
2106
146k
   if (ReadGrib1Sect4 (c_ipack + curLoc, gribLen, &curLoc, DSF, grib_Data,
2107
146k
                       meta, f_bms, bitmap, unitM, unitB) != 0) {
2108
109k
      free (bitmap);
2109
109k
      preErrSprintf ("Inside ReadGrib1Record\n");
2110
109k
      return -4;
2111
109k
   }
2112
37.9k
   if (f_bms) {
2113
12.2k
      free (bitmap);
2114
12.2k
   }
2115
2116
37.9k
   GRIB1_Table3LookUp (&(meta->pds1), &(meta->shortFstLevel),
2117
37.9k
                       &(meta->longFstLevel));
2118
/*   printf ("%s .. %s\n", meta->shortFstLevel, meta->longFstLevel);*/
2119
2120
/*
2121
   strftime (meta->refTime, 20, "%Y%m%d%H%M",
2122
             gmtime (&(meta->pds1.refTime)));
2123
*/
2124
37.9k
   Clock_Print (meta->refTime, 20, meta->pds1.refTime, "%Y%m%d%H%M", 0);
2125
2126
/*
2127
   strftime (meta->validTime, 20, "%Y%m%d%H%M",
2128
             gmtime (&(meta->pds1.validTime)));
2129
*/
2130
37.9k
   Clock_Print (meta->validTime, 20, meta->pds1.validTime, "%Y%m%d%H%M", 0);
2131
2132
37.9k
   double deltaTime = meta->pds1.validTime - meta->pds1.refTime;
2133
37.9k
   if (deltaTime >= std::numeric_limits<sInt4>::max()) {
2134
11
       printf ("Clamped deltaTime.  Was %lf\n", deltaTime);
2135
11
       deltaTime = std::numeric_limits<sInt4>::max();
2136
11
   }
2137
37.9k
   if (deltaTime <= std::numeric_limits<sInt4>::min()) {
2138
0
       printf ("Clamped deltaTime.  Was %lf\n", deltaTime);
2139
0
       deltaTime = std::numeric_limits<sInt4>::min();
2140
0
   }
2141
37.9k
   meta->deltTime = static_cast<sInt4>(deltaTime);
2142
2143
   /* Read section 5.  If it is "7777" == 926365495 we are done. */
2144
37.9k
   if (curLoc == gribLen) {
2145
34
      printf ("Warning: either gribLen did not account for section 5, or "
2146
34
              "section 5 is missing\n");
2147
34
      return 0;
2148
34
   }
2149
37.9k
   if (curLoc + 4 != gribLen) {
2150
18.7k
      errSprintf ("Invalid number of bytes for the end of the message.\n");
2151
18.7k
      return -5;
2152
18.7k
   }
2153
19.1k
   memcpy (&li_temp, c_ipack + curLoc, 4);
2154
19.1k
   if (li_temp != 926365495L) {
2155
12.6k
      errSprintf ("Did not find the end of the message.\n");
2156
12.6k
      return -5;
2157
12.6k
   }
2158
2159
6.45k
   return 0;
2160
19.1k
}
2161
2162
/*****************************************************************************
2163
 * main() --
2164
 *
2165
 * Arthur Taylor / MDL
2166
 *
2167
 * PURPOSE
2168
 *   To test the capabilities of this module, and give an example as to how
2169
 * ReadGrib1Record expects to be called.
2170
 *
2171
 * ARGUMENTS
2172
 * argc = The number of arguments on the command line. (Input)
2173
 * argv = The arguments on the command line. (Input)
2174
 *
2175
 * FILES/DATABASES:
2176
 *   A GRIB1 file.
2177
 *
2178
 * RETURNS: int
2179
 *  0 = OK
2180
 *
2181
 * HISTORY
2182
 *   4/2003 Arthur Taylor (MDL/RSIS): Created
2183
 *   6/2003 Matthew T. Kallio (matt@wunderground.com):
2184
 *          "wmo" dimension increased to WMO_HEADER_LEN + 1 (for '\0' char)
2185
 *
2186
 * NOTES
2187
 *****************************************************************************
2188
 */
2189
#ifdef DEBUG_DEGRIB1
2190
int main (int argc, char **argv)
2191
{
2192
   VSILFILE * grib_fp;       /* The opened grib2 file for input. */
2193
   char *buff = nullptr;
2194
   uInt4 buffLen = 0;
2195
   sInt4 sect0[SECT0LEN_WORD] = { 0 }; /* Holds the current Section 0. */
2196
   uInt4 gribLen;       /* Length of the current GRIB message. */
2197
   char *msg;
2198
   int version;
2199
   sChar f_unit = 0;
2200
   double *grib_Data;
2201
   uInt4 grib_DataLen;
2202
   grib_MetaData meta;
2203
2204
   double majEarth = 0.0;  // -radEarth if < 6000 ignore, otherwise use this
2205
                           // to override the radEarth in the GRIB1 or GRIB2
2206
                           // message.  Needed because NCEP uses 6371.2 but
2207
                           // GRIB1 could only state 6367.47.
2208
   double minEarth = 0.0;  // -minEarth if < 6000 ignore, otherwise use this
2209
                           // to override the minEarth in the GRIB1 or GRIB2
2210
                           // message.
2211
2212
2213
   IS_dataType is;      /* Un-parsed meta data for this GRIB2 message. As
2214
                         * well as some memory used by the unpacker. */
2215
2216
   if ((grib_fp = VSIFOpenL (argv[1], "rb")) == NULL) {
2217
      printf ("Problems opening %s for read\n", argv[1]);
2218
      return 1;
2219
   }
2220
   IS_Init (&is);
2221
   MetaInit (&meta);
2222
2223
   if (ReadSECT0 (grib_fp, &buff, &buffLen, -1, sect0, &gribLen, &version) < 0) {
2224
      VSIFCloseL(grib_fp);
2225
      free(buff);
2226
      msg = errSprintf (NULL);
2227
      printf ("%s\n", msg);
2228
      return -1;
2229
   }
2230
   free(buff);
2231
2232
   grib_DataLen = 0;
2233
   grib_Data = NULL;
2234
   if (version == 1) {
2235
      meta.GribVersion = version;
2236
      ReadGrib1Record (grib_fp, f_unit, &grib_Data, &grib_DataLen, &meta,
2237
                       &is, sect0, gribLen, majEarth, minEarth);
2238
   }
2239
2240
   MetaFree (&meta);
2241
   IS_Free (&is);
2242
   free (grib_Data);
2243
   VSIFCloseL(grib_fp);
2244
   return 0;
2245
}
2246
#endif