bufr2synop 0.24.0
bufrtotac_io.c
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2013-2022 by Guillermo Ballester Valor *
3 * gbv@ogimet.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20/*!
21 \file bufrtotac_io.c
22 \brief file with the i/o code for binary bufrtotac
23 */
24#ifndef CONFIG_H
25# include "config.h"
26# define CONFIG_H
27#endif
28
29#include "bufrtotac.h"
30
32{
34 printf ( "\nUsage: \n" );
35 printf ( "%s -i input_file [-i input] [-I list_of_files] [-t bufrtable_dir] [-o output] [-s] [-v][-j][-x][-X][-c][-h][more optional args....]\n", SELF );
36 printf ( " -c. The output is in csv format\n" );
37 printf ( " -D debug level. 0 = No debug, 1 = Debug, 2 = Verbose debug (default = 0)\n" );
38 printf ( " -E. Print expanded tree in json format\n" );
39 printf ( " -G. Print latitude, logitude and altitude \n" );
40 printf ( " -g. Print WIGOS ID\n" );
41 printf ( " -h Print this help\n" );
42 printf ( " -i Input file. Complete input path file for bufr file\n" );
43 printf ( " -I list_of_files. Pathname of a file with the list of files to parse, one filename per line\n" );
44 printf ( " -j. The output is in json format\n" );
45 printf ( " -J. Output expanded subset SEC 4 data in json format\n");
46 printf ( " -n. Do not try to decode to TAC, just parse BUFR report\n" );
47 printf ( " -o output. Pathname of output file. Default is standar output\n" );
48 printf ( " -R. Read bit_offsets file if exists. The path of these files is to add '.offs' to the name of input BUFR file\n");
49 printf ( " -s prints a long output with explained sequence of descriptors\n" );
50 printf ( " -S first..last . Print only results for subsets in range first..last (First subset available is 0). Default is all subsets\n" );
51 printf ( " -t bufrtable_dir. Pathname of bufr tables directory. Ended with '/'\n" );
52 printf ( " -T. Use cache of tables to optimize execution time\n");
53 printf ( " -W. Write bit_offsets file. The path of these files is to add '.offs' to the name of input BUFR file\n");
54 printf ( " -V. Verbose output\n" );
55 printf ( " -v. Print version\n" );
56 printf ( " -x. The output is in xml format\n" );
57 printf ( " -X. Try to extract an embebed bufr in a file seraching for a first '7777' after first 'BUFR'\n" );
58 printf ( " -0. Prints BUFR Sec 0 information in json format\n");
59 printf ( " -1. Prints BUFR Sec 1 information in json format\n");
60 printf ( " -2. Prints BUFR Sec 2 information in json format\n");
61 printf ( " -3. Prints BUFR Sec 3 information in json format\n");
62}
63
64/*!
65 \fn char *bufrtotac_get_version(char *version, char *build, char *builder, int *version_major, int *version_minor, int *version_patch)
66 \brief Get strings with version information and build date and time
67 \param version pointer to string with version as result if not NULL
68 \param dversion dimension of string \ref version
69 \param build pointer to string with compiler and compilation date and time if not NULL
70 \param dbuild dimension of string \ref build
71 \param builder pointer to string with builder utility. 'cmake' or 'autotools' if not NULL
72 \param dbuilder dimension of string \ref builder
73 \param version_major pointer to string with version_major component if not NULL
74 \param version_minor pointer to string with version_minor component if not NULL
75 \param version_patch pointer to string with version_patch component if not NULL
76
77 Retuns string pointer \ref version.
78 */
79char *bufrtotac_get_version(char *version, size_t dversion, char *build, size_t dbuild, char *builder, size_t dbuilder,
80 int *version_major, int *version_minor, int *version_patch)
81{
82 int major = 0, minor = 0, patch = 0;
83 size_t used;
84
85 if (version == NULL)
86 return NULL;
87 snprintf(version, dversion, "%s", VERSION);
88 // default
89 sscanf(version, "%d.%d.%d", &major, &minor, &patch);
90
91 if (build)
92 {
93 used = 0;
94#if defined(__INTEL_COMPILER)
95 used += snprintf(build + used, dbuild - used, "using INTEL C compiler icc %d.%d ", __INTEL_COMPILER, __INTEL_COMPILER_UPDATE);
96#elif defined(__clang_version__)
97 used += snprintf(build + used, dbuild - used, "using clang C compiler ", __clang_version__);
98#elif defined(__GNUC__)
99 used += snprintf(build + used, dbuild - used, "using GNU C compiler gcc %d.%d.%d ", __GNUC__ , __GNUC_MINOR__ , __GNUC_PATCHLEVEL__);
100#elif defined(_MSC_VER)
101 used += snprintf(build + used, dbuild - used, "using MICROSOFT C compiler %d ", _MSC_VER);
102#else
103 used += snprintf(build + used, dbuild - used, "using an unknown C compiler ");
104#endif
105 snprintf(build + used, dbuild - used,"at %s %s",__DATE__,__TIME__);
106 }
107
108 if (builder)
109#ifdef BUILD_USING_CMAKE
110 strncpy(builder, "cmake", dbuilder);
111#else
112 strncpy(builder, "autotools", dbuilder);
113#endif
114 if (version_major)
115 *version_major = major;
116 if (version_minor)
117 *version_minor = minor;
118 if (version_patch)
119 *version_patch = patch;
120 return version;
121}
122
123
125{
126 char version[16], build[128], builder[32];
127
128 bufrtotac_get_version ( version, sizeof (version), build, sizeof (build), builder, sizeof (builder), NULL, NULL, NULL );
129 printf ( "%s: Version '%s' built %s and %s.\n", SELF, VERSION, build, builder );
130 bufr2tac_get_version ( version, sizeof (version), build, sizeof (build), builder, sizeof (builder), NULL, NULL, NULL );
131 printf ( "Linked to bufr2tac library version '%s' built %s and %s.\n", version, build, builder );
132 bufrdeco_get_version ( version, sizeof (version), build, sizeof (build), builder, sizeof (builder), NULL, NULL, NULL );
133 printf ( "Linked to bufrdeco library version '%s' built %s and %s.\n", version, build, builder );
134}
135
136
137/*!
138 \fn int read_args( int _argc, char * _argv[])
139 \brief read the arguments from stdio
140 \param _argc number of arguments passed
141 \param _argv array of arguments
142
143 Returns 1 if succcess, -1 othewise
144*/
145int bufrtotac_read_args ( int _argc, char * _argv[] )
146{
147 int iopt;
148 char *c;
149 char aux[128];
150
151 // Initial and default values
152 INPUTFILE[0] = '\0';
153 OUTPUTFILE[0] = '\0';
154 LISTOFFILES[0] = '\0';
155 BUFRTABLES_DIR[0] = '\0';
156 VERBOSE = 0;
157 SHOW_SEQUENCE = 0;
158 DEBUG = 0;
159 NFILES = 0;
160 XML = 0;
161 JSON = 0;
162 CSV= 0;
163 EXTRACT = 0;
164 HTML = 0;
165 NOTAC = 0;
166 FIRST_SUBSET = 0;
167 LAST_SUBSET = -1;
168 PRINT_WIGOS_ID = 0;
169 READ_OFFSETS = 0;
170 WRITE_OFFSETS = 0;
171 USE_CACHE = 0;
172 PRINT_JSON_DATA = 0;
173 PRINT_JSON_SEC1 = 0;
174 PRINT_JSON_SEC2 = 0;
175 PRINT_JSON_SEC3 = 0;
177
178 /*
179 Read input options
180 */
181 while ( ( iopt = getopt ( _argc, _argv, "cD:Ehi:jJHI:no:S:st:TvgGVWRxX0123" ) ) !=-1 )
182 switch ( iopt )
183 {
184 case 'i':
185 if ( strlen ( optarg ) < 256 )
186 {
187 strcpy ( INPUTFILE, optarg );
188 snprintf( OFFSETFILE, sizeof (OFFSETFILE), "%s.offs", INPUTFILE);
189 }
190 break;
191
192 case 'E':
194 break;
195
196 case 'j':
197 JSON = 1;
198 break;
199
200 case 'J':
201 PRINT_JSON_DATA = 1;
202 break;
203
204 case 'I':
205 if ( strlen ( optarg ) < 256 )
206 strcpy ( LISTOFFILES, optarg );
207 break;
208
209 case 'n':
210 NOTAC = 1;
211 break;
212
213 case 'o':
214 if ( strlen ( optarg ) < 256 )
215 strcpy ( OUTPUTFILE, optarg );
216 break;
217
218 case 't':
219 if ( strlen ( optarg ) < 256 )
220 {
221 strcpy ( BUFRTABLES_DIR, optarg );
222 }
223 break;
224
225 case 'T':
226 USE_CACHE = 1;
227 break;
228
229 case 'D':
230 if ( strlen ( optarg ) < 2 )
231 {
232 DEBUG = atoi ( optarg );
233 if (DEBUG < 3)
234 bufr2tac_set_debug_level ( DEBUG ); // set debug level to bufr2tac library
235 }
236 break;
237
238 case 'H':
239 HTML = 1;
240 break;
241
242 case 'V':
243 VERBOSE = 1;
244 break;
245
246 case 'v':
248 exit ( EXIT_SUCCESS );
249 break;
250
251 case 's':
252 SHOW_SEQUENCE = 1;
253 break;
254
255 case 'S':
256 // Process subset sequence to show
257 if ( strlen ( optarg ) < 128 &&
258 strspn ( optarg, "0123456789." ) == strlen ( optarg ) )
259 {
260 if ( strstr ( optarg, ".." ) != NULL )
261 {
262 strcpy ( aux, optarg );
263 c = strstr ( aux, ".." );
264 if ( strlen ( c ) > 2 )
265 {
266 LAST_SUBSET = atoi ( c + 2 );
267 }
268 *c = '\0';
269 if ( aux[0] )
270 {
271 FIRST_SUBSET = atoi ( aux );
272 }
273 }
274 else
275 {
276 FIRST_SUBSET = atoi ( optarg );
278 }
279 }
280 break;
281
282 case 'x':
283 XML = 1;
284 break;
285
286 case 'c':
287 CSV = 1;
288 break;
289
290 case 'X':
291 EXTRACT = 1;
292 break;
293
294 case 'g':
295 PRINT_WIGOS_ID = 1;
296 break;
297
298 case 'G':
299 PRINT_GEO = 1;
300 break;
301
302 case 'W':
303 WRITE_OFFSETS = 1;
304 break;
305
306 case 'R':
307 READ_OFFSETS = 1;
308 break;
309
310 case '0':
311 PRINT_JSON_SEC0 = 1;
312 break;
313
314 case '1':
315 PRINT_JSON_SEC1 = 1;
316 break;
317
318 case '2':
319 PRINT_JSON_SEC2 = 1;
320 break;
321
322 case '3':
323 PRINT_JSON_SEC3 = 1;
324 break;
325
326 case 'h':
327 default:
329 exit ( EXIT_SUCCESS );
330 }
331
332 if ( INPUTFILE[0] == 0 && LISTOFFILES[0] == 0 )
333 {
334 printf ( "read_args(): It is needed an input file. Use -i or -I option\n" );
336 return -1;
337 }
338
339 // Open oututfile if needed or stdout
340 if (OUTPUTFILE[0])
341 {
342 if ((OUT = fopen (OUTPUTFILE,"w")) == NULL)
343 {
344 printf ( "%s(): Cannot open file %s to write to\n", __func__ , OUTPUTFILE);
346 return -1;
347 }
348 }
349 else
350 OUT = stdout;
351
352 return 1;
353}
354
355/* this is an interface to use bufr2tac */
357 struct bufrdeco *b, char *err )
358{
359 size_t i;
360 int ksec1[40], res;
361 int *kdtlst;
362 size_t nlst = ( size_t ) b->sec3.ndesc;
363
364 // memory for kdtlst
365 if ( ( kdtlst = ( int * ) calloc ( 1, nlst * sizeof ( int ) ) ) == NULL )
366 {
367 sprintf ( err, "decobufr_parse_subset_sequence(): cannot alloc memory for kdtlst\n" );
368 return 1;
369 }
370
371 // sets descriptor as integer according to ECMWF
372 for ( i = 0; i < nlst ; i++ )
373 {
374 descriptor_to_integer ( &kdtlst[i], &b->sec3.unexpanded[i] );
375 }
376
377 // And now set only used ksec1 elements
378 ksec1[5] = b->sec1.category;
379 ksec1[6] = b->sec1.subcategory_local;
380
381 // Finaly we call to bufr2tac library
383
384 // Set the subset being parsed
385 m->subset = SUBSET;
386
387 if (PRINT_WIGOS_ID)
389
390 if (PRINT_GEO)
392
393
394 m->h = &b->header;
395 res = parse_subset_sequence ( m, &b->seq, st, kdtlst, nlst, ksec1, err );
396 free ( ( void * ) kdtlst );
397 return res;
398}
399
400/*!
401 \fn char * get_bufrfile_path( char *filename, char *fileoffset, *err)
402 \brief Get bufr file names to parse
403 \param filename string where the file is on output
404 \param err string where to set the error if any
405
406 If success, it returns a pointer to filename. If there is no more files
407 to parse, or error returns NULL.
408
409 This routine is also opens the file with file list and close it when no more
410 file available in list
411
412 The content format in LISTOFFILES is compatible with 'ls -1'. Example assume we
413 want to parse all *.bufr files in current directory, we can do
414
415 \code
416 ls -1 *.bufr > list_file && bufrtotac -I list_file
417 \endcode
418*/
419char * get_bufrfile_path ( char *filename, char *fileoffset, char *err )
420{
421 char aux[256], *c;
422 if ( LISTOFFILES[0] == 0 )
423 {
424 if ( NFILES == 0 )
425 {
426 if ( filename != INPUTFILE )
427 strcpy ( filename, INPUTFILE );
428 return filename;
429 }
430 else
431 return 0;
432 }
433 else if ( NFILES == 0 )
434 {
435 if ( ( FL = fopen ( LISTOFFILES,"r" ) ) == NULL )
436 {
437 sprintf ( err,"Cannot open '%s'", LISTOFFILES );
438 return NULL;
439 }
440 }
441 if ( fgets ( aux, 256, FL ) )
442 {
443 c = strrchr ( aux,'\n' );
444 if ( c )
445 *c = 0;
446 strcpy ( filename, aux );
447 snprintf (fileoffset, BUFRDECO_PATH_LENGTH , "%s.offs", filename);
448 return filename;
449 }
450 else
451 {
452 fclose ( FL );
453 return NULL;
454 }
455}
456
457/*!
458 * \fn int bufrtotac_set_bufrdeco_bitmask (struct bufrdeco *b)
459 * \brief Set the bufrdeco struct bitmask according with readed args from shell
460 * \param b Pointer to struct \ref bufrdeco already inited
461 * \return 0 if succeded
462 */
464{
465 bufrdeco_assert ( b != NULL);
466
467 if ( HTML )
469
470 if (USE_CACHE)
472
473 if (PRINT_JSON_DATA)
475
476 if (PRINT_JSON_SEC0)
478
479 if (PRINT_JSON_SEC1)
481
482 if (PRINT_JSON_SEC2)
484
485 if (PRINT_JSON_SEC3)
487
490
491 return 0;
492}
int PRINT_JSON_EXPANDED_TREE
Definition: bufrdeco_json.c:33
int PRINT_JSON_SEC1
Definition: bufrdeco_json.c:29
int PRINT_JSON_SEC2
Definition: bufrdeco_json.c:30
int PRINT_JSON_SEC0
Definition: bufrdeco_json.c:28
int PRINT_JSON_SEC3
Definition: bufrdeco_json.c:31
int FIRST_SUBSET
Definition: bufrdeco_json.c:34
int EXTRACT
Definition: bufrdeco_json.c:26
int LAST_SUBSET
Definition: bufrdeco_json.c:35
char * bufr2tac_get_version(char *version, size_t dversion, char *build, size_t dbuild, char *builder, size_t dbuilder, int *version_major, int *version_minor, int *version_patch)
Definition: bufr2tac.c:48
int bufr2tac_set_debug_level(int level)
Definition: bufr2tac.c:93
#define PRINT_BITMASK_WIGOS
Bit mask to member print_mask in struct metreport to print WIGOS Identifier.
Definition: bufr2tac.h:208
int parse_subset_sequence(struct metreport *m, struct bufr_subset_sequence_data *sq, struct bufr2tac_subset_state *st, int *kdtlst, size_t nlst, int *ksec1, char *err)
Parse a sequence of expanded descriptors for a subset.
void bufr2tac_clean_metreport(struct metreport *m)
#define PRINT_BITMASK_GEO
Bit mask to member print_mask in struct metreport to print geographic position.
Definition: bufr2tac.h:214
int descriptor_to_integer(int *id, struct bufr_descriptor *d)
parse a descriptor and sets an integer in the decimal formas fxxyyy
char * bufrdeco_get_version(char *version, size_t dversion, char *build, size_t dbuild, char *builder, size_t dbuilder, int *version_major, int *version_minor, int *version_patch)
Definition: bufrdeco.c:50
#define bufrdeco_assert(__my_expr__)
Check a expression and exit if it fails.
Definition: bufrdeco.h:374
#define BUFRDECO_OUTPUT_JSON_EXPANDED_TREE
Bit mask to the member mask of struct bufrdeco to print bufr expanded tree of descriptors.
Definition: bufrdeco.h:305
#define BUFRDECO_OUTPUT_JSON_SUBSET_DATA
Bit mask to the member mask of struct bufrdeco to print bufr subset data in json format.
Definition: bufrdeco.h:299
#define BUFRDECO_OUTPUT_JSON_SEC2
Bit mask to the member mask of struct bufrdeco to print bufr info for SEC 2 in json format.
Definition: bufrdeco.h:287
#define BUFRDECO_OUTPUT_JSON_SEC3
Bit mask to the member mask of struct bufrdeco to print bufr info for SEC 3 in json format.
Definition: bufrdeco.h:293
#define BUFRDECO_OUTPUT_JSON_SEC0
Bit mask to the member mask of struct bufrdeco to print info for SEC 0 in json format.
Definition: bufrdeco.h:275
#define BUFRDECO_OUTPUT_HTML
Bit mask to the member mask for struct bufrdeco to format output as html for SECs 0 to 3.
Definition: bufrdeco.h:256
#define BUFRDECO_OUTPUT_JSON_SEC1
Bit mask to the member mask of struct bufrdeco to print info for SEC 1 in json format.
Definition: bufrdeco.h:281
#define BUFRDECO_PATH_LENGTH
Length for files/directory path strings.
Definition: bufrdeco.h:335
#define BUFRDECO_USE_TABLES_CACHE
Bit mask to the member mask of struct bufrdeco to mark the use of bufr_tables cache.
Definition: bufrdeco.h:268
int VERBOSE
Definition: bufrnoaa.c:192
int JSON
Definition: bufrtotac.c:107
char OUTPUTFILE[256]
Definition: bufrtotac.c:100
const char SELF[]
Definition: bufrtotac.c:94
int XML
Definition: bufrtotac.c:106
char INPUTFILE[256]
Definition: bufrtotac.c:98
FILE * OUT
Definition: bufrtotac.c:129
int PRINT_GEO
Definition: bufrtotac.c:116
int NFILES
Definition: bufrtotac.c:104
int DEBUG
Definition: bufrtotac.c:103
int WRITE_OFFSETS
Definition: bufrtotac.c:118
int READ_OFFSETS
Definition: bufrtotac.c:117
char LISTOFFILES[256]
Definition: bufrtotac.c:97
int CSV
Definition: bufrtotac.c:108
int SHOW_SEQUENCE
Definition: bufrtotac.c:102
int PRINT_JSON_DATA
Definition: bufrtotac.c:121
FILE * FL
Definition: bufrtotac.c:128
char OFFSETFILE[BUFRDECO_PATH_LENGTH+8]
Definition: bufrtotac.c:99
int SUBSET
Definition: bufrtotac.c:120
int USE_CACHE
Definition: bufrtotac.c:119
int HTML
Definition: bufrtotac.c:111
int NOTAC
Definition: bufrtotac.c:112
char BUFRTABLES_DIR[256]
Definition: bufrtotac.c:96
int PRINT_WIGOS_ID
Definition: bufrtotac.c:115
Include header file for binary bufrtotac.
int bufrtotac_parse_subset_sequence(struct metreport *m, struct bufr2tac_subset_state *st, struct bufrdeco *b, char *err)
Definition: bufrtotac_io.c:356
void bufrtotac_print_version()
Definition: bufrtotac_io.c:124
void bufrtotac_print_usage(void)
Definition: bufrtotac_io.c:31
char * get_bufrfile_path(char *filename, char *fileoffset, char *err)
Definition: bufrtotac_io.c:419
char * bufrtotac_get_version(char *version, size_t dversion, char *build, size_t dbuild, char *builder, size_t dbuilder, int *version_major, int *version_minor, int *version_patch)
Definition: bufrtotac_io.c:79
int bufrtotac_set_bufrdeco_bitmask(struct bufrdeco *b)
Set the bufrdeco struct bitmask according with readed args from shell.
Definition: bufrtotac_io.c:463
int bufrtotac_read_args(int _argc, char *_argv[])
Definition: bufrtotac_io.c:145
#define VERSION
Definition: config.h:8
stores information needed to parse a sequential list of expanded descriptors for a subset
Definition: bufr2tac.h:246
uint8_t category
Definition: bufrdeco.h:779
uint8_t subcategory_local
Definition: bufrdeco.h:781
struct bufr_descriptor unexpanded[BUFR_LEN_UNEXPANDED_DESCRIPTOR]
Definition: bufrdeco.h:814
uint32_t ndesc
Definition: bufrdeco.h:813
This struct contains all needed data to parse and decode a BUFR file.
Definition: bufrdeco.h:965
struct bufrdeco_subset_sequence_data seq
Definition: bufrdeco.h:979
uint32_t mask
Definition: bufrdeco.h:966
struct bufr_sec3 sec3
Definition: bufrdeco.h:971
struct gts_header header
Definition: bufrdeco.h:967
struct bufr_sec1 sec1
Definition: bufrdeco.h:969
all the information for a meteorological report in WMO text format from a BUFR file
Definition: bufr2tac.h:309
int subset
Definition: bufr2tac.h:311
int print_mask
Definition: bufr2tac.h:312
struct gts_header * h
Definition: bufr2tac.h:313