bufr2synop 0.24.0
bufrdeco_read.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 bufrdeco_read.c
22 \brief This file has the code to read bufr files
23*/
24#include "bufrdeco.h"
25
26
27/*!
28 \fn int bufrdeco_read_bufr ( struct bufrdeco *b, char *filename )
29 \brief Read bufr file and does preliminary and first decode pass
30 \param b pointer to struct \ref bufrdeco
31 \param filename complete path of BUFR file
32 \return 0 if all is OK, 1 otherwise
33
34 This function does the folowing tasks:
35 - Read the file and checks the marks at the begining and end to see wheter is a BUFR file
36 - Init the structs and allocate the needed memory if not done previously
37 - Splits and parse the BUFR sections (without expanding descriptors nor parsing data)
38 - Reads the needed Table files and store them in memory.
39
40 */
41int bufrdeco_read_bufr ( struct bufrdeco *b, char *filename )
42{
43 int aux, res;
44 uint8_t *bufrx = NULL; /*!< pointer to a memory buffer where we write raw bufr file */
45 buf_t n = 0;
46 FILE *fp;
47 struct stat st;
48
49 bufrdeco_assert ( b != NULL );
50
51 /* Stat input file */
52 if ( stat ( filename, &st ) < 0 )
53 {
54 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot stat file '%s'\n", __func__, filename );
55 return 1;
56 }
57
58 /* Alloc nedeed memory for bufr */
59 if ( S_ISREG ( st.st_mode ) || S_ISLNK ( st.st_mode ) )
60 {
61 if ( ( bufrx = ( uint8_t * ) calloc ( 1, st.st_size + 4 ) ) == NULL )
62 {
63 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot alloc memory for file '%s'\n", __func__, filename );
64 return 1;
65 }
66 }
67 else
68 {
69 snprintf ( b->error, sizeof ( b->error ), "%s(): '%s' is not a regular file nor symbolic link\n", __func__, filename );
70 return 1;
71 }
72
73 /* Inits bufr struct */
74 if ( ( st.st_size + 4 ) >= BUFR_LEN )
75 {
76 snprintf ( b->error, sizeof ( b->error ), "%s(): File '%s' too large. Consider increase BUFR_LEN\n", __func__, filename );
77 free ( ( void * ) bufrx );
78 return 1;
79 }
80
81 // Open and read the file
82 if ( ( fp = fopen ( filename, "r" ) ) == NULL )
83 {
84 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot open file '%s'\n", __func__, filename );
85 free ( ( void * ) bufrx );
86 return 1;
87 }
88
89 while ( ( aux = fgetc ( fp ) ) != EOF && ( int ) n < st.st_size )
90 bufrx[n++] = ( uint8_t ) aux;
91
92 //n = fread(&bufrx[0], 1, st.st_size, fp);
93 //bufrdeco_assert(n == (size_t)st.st_size);
94
95 // close the file
96
97 fclose ( fp );
98
99 res = bufrdeco_read_buffer ( b, bufrx, n );
100 free ( bufrx );
101 return res;
102}
103
104
105/*!
106 \fn int bufrdeco_extract_bufr ( struct bufrdeco *b, char *filename )
107 \brief Read file and try to find a bufr report inserted in. Once found do the same that bufrdeco_read_file()
108 \param b pointer to struct \ref bufrdeco
109 \param filename complete path of BUFR file
110 \return 0 if all is OK, 1 otherwise
111
112 This function does the folowing tasks:
113 - Try to find first buffer of bytes begining with 'BUFR' chars and ending with '7777'. This will be considered as a bufr file.
114 - Read the file and checks the marks at the begining and end to see wheter is a BUFR file
115 - Init the structs and allocate the needed memory if not done previously
116 - Splits and parse the BUFR sections (without expanding descriptors nor parsing data)
117 - Reads the needed Table files and store them in memory.
118
119 */
120int bufrdeco_extract_bufr ( struct bufrdeco *b, char *filename )
121{
122 int aux, res;
123 uint8_t *bufrx = NULL, *pbeg = NULL; /*!< pointer to a memory buffer where we write raw bufr file */
124 buf_t n = 0, beg, end, size = 0;
125 FILE *fp;
126 struct stat st;
127
128 bufrdeco_assert ( b != NULL );
129
130 /* Stat input file */
131 if ( stat ( filename, &st ) < 0 )
132 {
133 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot stat file '%s'\n", __func__, filename );
134 return 1;
135 }
136
137 /* Alloc nedeed memory for bufr */
138 if ( S_ISREG ( st.st_mode ) || S_ISLNK ( st.st_mode ) )
139 {
140 if ( ( bufrx = ( uint8_t * ) calloc ( 1, st.st_size + 4 ) ) == NULL )
141 {
142 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot alloc memory for file '%s'\n", __func__, filename );
143 return 1;
144 }
145 }
146 else
147 {
148 snprintf ( b->error, sizeof ( b->error ), "%s(): '%s' is not a regular file nor symbolic link\n", __func__, filename );
149 return 1;
150 }
151
152 /* Inits bufr struct */
153 if ( ( st.st_size + 4 ) >= BUFR_LEN )
154 {
155 snprintf ( b->error, sizeof ( b->error ), "%s(): File '%s' too large. Consider increase BUFR_LEN\n", __func__, filename );
156 free ( ( void * ) bufrx );
157 return 1;
158 }
159
160 // Open and read the file
161 if ( ( fp = fopen ( filename, "r" ) ) == NULL )
162 {
163 snprintf ( b->error, sizeof ( b->error ), "%s(): cannot open file '%s'\n", __func__, filename );
164 free ( ( void * ) bufrx );
165 return 1;
166 }
167
168 beg = end = st.st_size;
169 while ( ( aux = fgetc ( fp ) ) != EOF && ( int ) n < st.st_size )
170 {
171 bufrx[n++] = ( uint8_t ) aux;
172
173 // check if first 'BUFR' item has been found
174 if ( n >= 4 &&
175 bufrx[n - 4] == 'B' &&
176 bufrx[n - 3] == 'U' &&
177 bufrx[n - 2] == 'F' &&
178 bufrx[n - 1] == 'R' )
179 {
180 beg = n - 4;
181 pbeg = &bufrx[ n - 4];
182 }
183
184 // check if first '7777' has been found after first 'BUFR'
185 if ( n > 4 &&
186 beg < ( ( size_t ) st.st_size - 4 ) &&
187 bufrx[n - 4] == '7' &&
188 bufrx[n - 3] == '7' &&
189 bufrx[n - 2] == '7' &&
190 bufrx[n - 1] == '7' )
191 {
192 end = n - 1;
193 size = end - beg + 1;
194 }
195 }
196
197
198 // close the file
199 fclose ( fp );
200
201 if ( size < 8 )
202 {
203 snprintf ( b->error, sizeof ( b->error ), "%s(): not found a '7777' item after 'BUFR'\n", __func__ );
204 return 1;
205 }
206 res = bufrdeco_read_buffer ( b, pbeg, size );
207 free ( bufrx );
208 return res;
209}
210
211
212/*!
213 \fn int bufrdeco_read_buffer ( struct bufrdeco *b, uint8_t *bufrx, size_t size )
214 \brief Read a memory buffer and does preliminary and first decode pass
215 \param b pointer to struct \ref bufrdeco
216 \param bufrx buffer already allocated by caller
217 \param size size of BUFR in buffer
218 \return 0 if all is OK, 1 otherwise
219
220 This function does the folowing tasks:
221 - Splits and parse the BUFR sections (without expanding descriptors nor parsing data)
222 - Reads the needed Table files and store them in memory.
223
224 */
225int bufrdeco_read_buffer ( struct bufrdeco *b, uint8_t *bufrx, buf_t size )
226{
227 uint8_t *c;
228 buf_t ix, ud;
229
230 bufrdeco_assert ( b != NULL );
231
232 // Some fast checks
233 if ( ( size + 4 ) >= BUFR_LEN )
234 {
235 snprintf ( b->error, sizeof ( b->error ), "%s(): Buffer provided too large. Consider increase BUFR_LEN\n", __func__ );
236 return 1;
237 }
238
239 if ( size < 8 )
240 {
241 snprintf ( b->error, sizeof ( b->error ), "%s(): Too few bytes for a bufr\n", __func__ );
242 return 1;
243 }
244
245 // check if begins with BUFR
246 if ( bufrx[0] != 'B' || bufrx[1] != 'U' || bufrx[2] != 'F' || bufrx[3] != 'R' )
247 {
248 snprintf ( b->error, sizeof ( b->error ), "%s(): bufr file does not begin with 'BUFR' chars\n", __func__ );
249 return 1;
250 }
251
252 // check if end with '7777'
253 if ( bufrx[size - 4] != '7' || bufrx[size - 3] != '7' || bufrx[size - 2] != '7' || bufrx[size - 1] != '7' )
254 {
255 snprintf ( b->error, sizeof ( b->error ), "%s(): bufe file does not end with '7777' chars\n", __func__ );
256 return 1;
257 }
258
259 /******************* section 0 *****************************/
260
261 // we have already checked about begin and end
262
263 // length of whole message
264 b->sec0.bufr_length = three_bytes_to_uint32 ( &bufrx[4] );
265 // check if length is correct
266 if ( b->sec0.bufr_length != ( uint32_t ) size )
267 {
268 snprintf ( b->error, sizeof ( b->error ), "%s(): bufr file have %u bytes and it says %u\n", __func__,
269 ( uint32_t ) size, b->sec0.bufr_length );
270 return 1;
271 }
272
273 // set bufr edition number
274 b->sec0.edition = bufrx[7];
275
276 if ( b->sec0.edition < 3 )
277 {
278 snprintf ( b->error, sizeof ( b->error ), "%s(): Bufr edition must be 3 or superior and this file is coded with version %u\n", __func__, b->sec0.edition );
279 return 1;
280 }
281
282 // raw
283 memcpy ( &b->sec0.raw[0], &bufrx[0], 8 );
284
287
288 /******************* section 1 *****************************/
289 c = &bufrx[8]; // pointer to begin of sec1
290 switch ( b->sec0.edition )
291 {
292 case 3:
294 b->sec1.master = c[3];
295 b->sec1.subcentre = c[4];
296 b->sec1.centre = c[5];
297 b->sec1.update = c[6];
298 b->sec1.options = c[7];
299 b->sec1.category = c[8];
300 b->sec1.subcategory = c[9];
301 b->sec1.subcategory_local = 0; // not in version 3
302 b->sec1.master_version = c[10];
303 b->sec1.master_local = c[11];
304 if ( c[12] > 80 )
305 b->sec1.year = 1900 + c[12];
306 else
307 b->sec1.year = 2000 + c[12];
308 b->sec1.month = c[13];
309 b->sec1.day = c[14];
310 b->sec1.hour = c[15];
311 b->sec1.minute = c[16];
312 b->sec1.second = 0; // not in version 3
313 break;
314 case 4:
316 b->sec1.master = c[3];
317 b->sec1.centre = two_bytes_to_uint32 ( &c[4] );
318 b->sec1.subcentre = two_bytes_to_uint32 ( &c[6] );
319 b->sec1.update = c[8];
320 b->sec1.options = c[9];
321 b->sec1.category = c[10];
322 b->sec1.subcategory = c[11];
323 b->sec1.subcategory_local = c[12];
324 b->sec1.master_version = c[13];
325 b->sec1.master_local = c[14];
326 b->sec1.year = two_bytes_to_uint32 ( &c[15] );
327 b->sec1.month = c[17];
328 b->sec1.day = c[18];
329 b->sec1.hour = c[19];
330 b->sec1.minute = c[20];
331 b->sec1.second = c[21];
332 break;
333 default:
334 snprintf ( b->error, sizeof ( b->error ), "%s(): This file is coded with version %u and is not supported\n", __func__, b->sec0.edition );
335 free ( ( void * ) bufrx );
336 return 1;
337 }
338 memcpy ( b->sec1.raw, c, b->sec1.length ); // raw data
339 c += b->sec1.length;
340
343
344 /******************* section 2 (Optional) ******************/
345 if ( b->sec1.options & 0x80 )
346 {
348 memcpy ( b->sec2.raw, c, b->sec2.length );
349 c += b->sec2.length;
350 }
353
354 /******************* section 3 *****************************/
356 b->sec3.subsets = two_bytes_to_uint32 ( &c[4] );
357 if ( c[6] & 0x80 )
358 b->sec3.observed = 1;
359 else
360 b->sec3.observed = 0;
361 if ( c[6] & 0x40 )
362 b->sec3.compressed = 1;
363 else
364 b->sec3.compressed = 0;
365
366 // loop of unexpanded descriptors
367 for ( ix = 7, ud = 0; ( ix + 1 ) < b->sec3.length && ud < BUFR_LEN_UNEXPANDED_DESCRIPTOR; ix += 2 )
368 {
369 two_bytes_to_descriptor ( &b->sec3.unexpanded[ud], &c[ix] );
370 if ( b->sec3.unexpanded[ud].f || b->sec3.unexpanded[ud].x || b->sec3.unexpanded[ud].y )
371 ud++;
372 }
373 b->sec3.ndesc = ud;
374 memcpy ( b->sec3.raw, c, b->sec3.length );
375 c += b->sec3.length;
376
379
380 /******************* section 4 *****************************/
382 // we copy 4 byte more without danger because of latest '7777' and to use fastest exctracting bits algorithm
383 memcpy ( b->sec4.raw, c, b->sec4.length + 4 );
384
385 b->sec4.bit_offset = 32; // the first bit in byte 4
386
387#ifdef DEBUG_TIME
388 bufrdeco_clock_start = clock();
389#endif
390
391 if ( bufr_read_tables ( b ) )
392 {
393 return 1;
394 }
395#ifdef DEBUG_TIME
396 bufrdeco_clock_end = clock();
397 print_timing ( bufrdeco_clock_start, bufrdeco_clock_end,bufr_read_tables_wmo() );
398#endif
399
400 return 0;
401}
Include header file for bufrdeco library.
buf_t bufrdeco_print_json_sec2(FILE *out, struct bufrdeco *b)
Print info form optional sec 2 in json format.
uint32_t buf_t
Type to set offsets and dimension of arrays or counters used in bufrdeco.
Definition: bufrdeco.h:346
uint32_t two_bytes_to_uint32(const uint8_t *source)
returns the uint32_t value from an array of two bytes, most significant first
#define bufrdeco_assert(__my_expr__)
Check a expression and exit if it fails.
Definition: bufrdeco.h:374
uint32_t three_bytes_to_uint32(const uint8_t *source)
returns the uint32_t value from an array of three bytes, most significant first
buf_t bufrdeco_print_json_sec0(FILE *out, struct bufrdeco *b)
#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
int bufr_read_tables(struct bufrdeco *b)
Read the tables according with bufr file data from a bufr table directory.
Definition: bufrdeco_wmo.c:162
#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_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 BUFR_LEN_UNEXPANDED_DESCRIPTOR
Max amount of unexpanded descriptors in a SEC3.
Definition: bufrdeco.h:213
buf_t bufrdeco_print_json_sec3(FILE *out, struct bufrdeco *b)
Print info form sec 3 in json format.
#define BUFR_LEN
Max length of a BUFR file.
Definition: bufrdeco.h:60
buf_t bufrdeco_print_json_sec1(FILE *out, struct bufrdeco *b)
Print info form sec 1 in json format.
int two_bytes_to_descriptor(struct bufr_descriptor *d, const uint8_t *source)
set a struct bufr_descriptor from two consecutive bytes in bufr file
int bufrdeco_read_buffer(struct bufrdeco *b, uint8_t *bufrx, buf_t size)
int bufrdeco_extract_bufr(struct bufrdeco *b, char *filename)
Read file and try to find a bufr report inserted in. Once found do the same that bufrdeco_read_file()
int bufrdeco_read_bufr(struct bufrdeco *b, char *filename)
Read bufr file and does preliminary and first decode pass.
Definition: bufrdeco_read.c:41
uint8_t raw[8]
Definition: bufrdeco.h:699
uint8_t edition
Definition: bufrdeco.h:698
uint32_t bufr_length
Definition: bufrdeco.h:697
uint8_t month
Definition: bufrdeco.h:785
uint32_t year
Definition: bufrdeco.h:784
uint8_t master_local
Definition: bufrdeco.h:783
uint32_t subcentre
Definition: bufrdeco.h:776
uint32_t centre
Definition: bufrdeco.h:775
uint8_t category
Definition: bufrdeco.h:779
uint8_t options
Definition: bufrdeco.h:778
uint8_t minute
Definition: bufrdeco.h:788
uint8_t subcategory
Definition: bufrdeco.h:780
uint8_t master_version
Definition: bufrdeco.h:782
uint8_t second
Definition: bufrdeco.h:789
uint8_t day
Definition: bufrdeco.h:786
uint32_t length
Definition: bufrdeco.h:773
uint8_t subcategory_local
Definition: bufrdeco.h:781
uint8_t raw[BUFR_LEN_SEC1]
Definition: bufrdeco.h:790
uint8_t hour
Definition: bufrdeco.h:787
uint8_t update
Definition: bufrdeco.h:777
uint8_t master
Definition: bufrdeco.h:774
uint32_t length
Definition: bufrdeco.h:799
uint8_t raw[BUFR_LEN_SEC2]
Definition: bufrdeco.h:800
uint8_t observed
Definition: bufrdeco.h:811
uint8_t compressed
Definition: bufrdeco.h:812
struct bufr_descriptor unexpanded[BUFR_LEN_UNEXPANDED_DESCRIPTOR]
Definition: bufrdeco.h:814
uint32_t ndesc
Definition: bufrdeco.h:813
uint32_t length
Definition: bufrdeco.h:809
uint32_t subsets
Definition: bufrdeco.h:810
uint8_t raw[BUFR_LEN_SEC3]
Definition: bufrdeco.h:815
uint32_t length
Definition: bufrdeco.h:826
uint8_t raw[BUFR_LEN]
Definition: bufrdeco.h:828
size_t bit_offset
Definition: bufrdeco.h:827
This struct contains all needed data to parse and decode a BUFR file.
Definition: bufrdeco.h:965
struct bufr_sec0 sec0
Definition: bufrdeco.h:968
uint32_t mask
Definition: bufrdeco.h:966
struct bufr_sec4 sec4
Definition: bufrdeco.h:972
struct bufr_sec2 sec2
Definition: bufrdeco.h:970
struct bufr_sec3 sec3
Definition: bufrdeco.h:971
FILE * out
Definition: bufrdeco.h:984
char error[1024]
Definition: bufrdeco.h:983
struct bufr_sec1 sec1
Definition: bufrdeco.h:969