/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, ¢er, &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, ¢er, &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 |