bufr2synop 0.24.0
Functions
bufrdeco_read.c File Reference

This file has the code to read bufr files. More...

#include "bufrdeco.h"
Include dependency graph for bufrdeco_read.c:

Go to the source code of this file.

Functions

int bufrdeco_read_bufr (struct bufrdeco *b, char *filename)
 Read bufr file and does preliminary and first decode pass. More...
 
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() More...
 
int bufrdeco_read_buffer (struct bufrdeco *b, uint8_t *bufrx, buf_t size)
 

Detailed Description

This file has the code to read bufr files.

Definition in file bufrdeco_read.c.

Function Documentation

◆ bufrdeco_extract_bufr()

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()

Parameters
bpointer to struct bufrdeco
filenamecomplete path of BUFR file
Returns
0 if all is OK, 1 otherwise

This function does the folowing tasks:

  • Try to find first buffer of bytes begining with 'BUFR' chars and ending with '7777'. This will be considered as a bufr file.
  • Read the file and checks the marks at the begining and end to see wheter is a BUFR file
  • Init the structs and allocate the needed memory if not done previously
  • Splits and parse the BUFR sections (without expanding descriptors nor parsing data)
  • Reads the needed Table files and store them in memory.

< pointer to a memory buffer where we write raw bufr file

Definition at line 120 of file bufrdeco_read.c.

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}
uint32_t buf_t
Type to set offsets and dimension of arrays or counters used in bufrdeco.
Definition: bufrdeco.h:346
#define bufrdeco_assert(__my_expr__)
Check a expression and exit if it fails.
Definition: bufrdeco.h:374
#define BUFR_LEN
Max length of a BUFR file.
Definition: bufrdeco.h:60
int bufrdeco_read_buffer(struct bufrdeco *b, uint8_t *bufrx, buf_t size)
char error[1024]
Definition: bufrdeco.h:983

References BUFR_LEN, bufrdeco_assert, bufrdeco_read_buffer(), and bufrdeco::error.

Referenced by bufrdeco_get_bufr(), and main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bufrdeco_read_buffer()

int bufrdeco_read_buffer ( struct bufrdeco b,
uint8_t *  bufrx,
buf_t  size 
)

Definition at line 225 of file bufrdeco_read.c.

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}
buf_t bufrdeco_print_json_sec2(FILE *out, struct bufrdeco *b)
Print info form optional sec 2 in json format.
uint32_t two_bytes_to_uint32(const uint8_t *source)
returns the uint32_t value from an array of two bytes, most significant first
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.
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
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
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
struct bufr_sec1 sec1
Definition: bufrdeco.h:969

References bufr_sec4::bit_offset, BUFR_LEN, BUFR_LEN_UNEXPANDED_DESCRIPTOR, bufr_sec0::bufr_length, bufr_read_tables(), bufrdeco_assert, BUFRDECO_OUTPUT_JSON_SEC0, BUFRDECO_OUTPUT_JSON_SEC1, BUFRDECO_OUTPUT_JSON_SEC2, BUFRDECO_OUTPUT_JSON_SEC3, bufrdeco_print_json_sec0(), bufrdeco_print_json_sec1(), bufrdeco_print_json_sec2(), bufrdeco_print_json_sec3(), bufr_sec1::category, bufr_sec1::centre, bufr_sec3::compressed, bufr_sec1::day, bufr_sec0::edition, bufrdeco::error, bufr_descriptor::f, bufr_sec1::hour, bufr_sec1::length, bufr_sec2::length, bufr_sec3::length, bufr_sec4::length, bufrdeco::mask, bufr_sec1::master, bufr_sec1::master_local, bufr_sec1::master_version, bufr_sec1::minute, bufr_sec1::month, bufr_sec3::ndesc, bufr_sec3::observed, bufr_sec1::options, bufrdeco::out, bufr_sec0::raw, bufr_sec4::raw, bufr_sec1::raw, bufr_sec2::raw, bufr_sec3::raw, bufrdeco::sec0, bufrdeco::sec1, bufrdeco::sec2, bufrdeco::sec3, bufrdeco::sec4, bufr_sec1::second, bufr_sec1::subcategory, bufr_sec1::subcategory_local, bufr_sec1::subcentre, bufr_sec3::subsets, three_bytes_to_uint32(), two_bytes_to_descriptor(), two_bytes_to_uint32(), bufr_sec3::unexpanded, bufr_sec1::update, bufr_descriptor::x, bufr_descriptor::y, and bufr_sec1::year.

Referenced by bufrdeco_extract_bufr(), and bufrdeco_read_bufr().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bufrdeco_read_bufr()

int bufrdeco_read_bufr ( struct bufrdeco b,
char *  filename 
)

Read bufr file and does preliminary and first decode pass.

Parameters
bpointer to struct bufrdeco
filenamecomplete path of BUFR file
Returns
0 if all is OK, 1 otherwise

This function does the folowing tasks:

  • Read the file and checks the marks at the begining and end to see wheter is a BUFR file
  • Init the structs and allocate the needed memory if not done previously
  • Splits and parse the BUFR sections (without expanding descriptors nor parsing data)
  • Reads the needed Table files and store them in memory.

< pointer to a memory buffer where we write raw bufr file

Definition at line 41 of file bufrdeco_read.c.

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}

References BUFR_LEN, bufrdeco_assert, bufrdeco_read_buffer(), and bufrdeco::error.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function: