bufr2synop 0.24.0
bufrdeco_tableC.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_tableC.c
22 \brief file with the code to read table C data (code and flag tables)
23 */
24#include "bufrdeco.h"
25
26
27/*!
28 \fn int bufr_read_tableC ( struct bufrdeco *b )
29 \brief Reads a file with table C content (Code table and bit flags) according with csv WMO format
30 \param b pointer to a target struct \ref bufrdeco
31 \return 0 if success, 1 otherwise
32*/
33int bufr_read_tableC ( struct bufrdeco *b )
34{
35 char *c;
36 //size_t used = 0;
37 FILE *t;
38 int nt;
39 uint32_t ix;
40 buf_t i = 0;
41 struct bufr_descriptor desc;
42 struct bufr_tableC *tc;
43 char *tk[16];
44 char caux[256], l[CSV_MAXL];
45
46 //bufrdeco_assert ( b != NULL );
47
48 tc = & ( b->tables->c );
49
50 if ( tc->path[0] == 0 )
51 {
52 return 1;
53 }
54
55 // If we've already readed this table.
56 if ( strcmp ( tc->path, tc->old_path ) == 0 )
57 {
58#ifdef __DEBUG
59 printf ("# Reused table %s\n", tc->path);
60#endif
61 return 0; // all done
62 }
63
64 strcpy ( caux, tc->path );
65 memset ( tc, 0, sizeof ( struct bufr_tableC ) );
66 strcpy ( tc->path, caux );
67 if ( ( t = fopen ( tc->path, "r" ) ) == NULL )
68 {
69 snprintf ( b->error, sizeof ( b->error ),"Unable to open table C file '%s'\n", tc->path );
70 return 1;
71 }
72
73 // read first line, it is ignored
74 fgets ( l, CSV_MAXL, t );
75
76 while ( fgets ( l, CSV_MAXL, t ) != NULL && i < BUFR_MAXLINES_TABLEC )
77 {
78
79 // Parse line
80 if ( parse_csv_line ( &nt, tk, l ) < 0 || nt != 6 )
81 {
82 snprintf ( b->error, sizeof ( b->error ),"Error parsing csv line from table C file '%s'. Found %d fields in line %u \n", tc->path, nt, i );
83 return 1;
84 }
85
86 // Check if code contains other than non-numeric i.e. 'All' or '-'
87 // In this case, the line is ignored
88 if ( tk[1][0] == 0 || strchr ( tk[1], '-' ) != NULL || strstr ( tk[1], "All" ) != NULL )
89 continue;
90
91 // Key
92 // First we build the descriptor
93 ix = strtoul ( tk[0], &c, 10 );
94 uint32_t_to_descriptor ( &desc, ix );
95 strcpy ( tc->item[i].key, tk[0] );
96 tc->item[i].x = desc.x;
97 tc->item[i].y = desc.y;
98
99 // Integer value
100 tc->item[i].ival = strtoul ( tk[1], &c, 10 );
101
102 // Description
103 c = & tc->item[i].description[0];
104 snprintf ( c, BUFR_EXPLAINED_LENGTH, "%s %s %s %s", tk[2], tk[3], tk[4], tk[5] );
105
106 if ( tc->num[desc.x] == 0 )
107 {
108 tc->x_start[desc.x] = i; // marc the start
109 }
110 if ( tc->y_ref[desc.x][desc.y] == 0 )
111 {
112 tc->y_ref[desc.x][desc.y] = i - tc->x_start[desc.x]; // marc the position from start of first x
113 }
114 ( tc->num[desc.x] ) ++;
115 i++;
116 }
117 fclose ( t );
118 tc->nlines = i;
119 tc->wmo_table = 1;
120 strcpy ( tc->old_path, tc->path ); // store latest path
121 return 0;
122}
123
124
125/*!
126 \fn int bufr_find_tableC_csv_index ( buf_t *index, struct bufr_tableb *tb, const char *key, uint32_t code )
127 \brief found a descriptor index in a struct \ref bufr_tableC
128 \param index pointer to a size_t where to set the result if success
129 \param tb pointer to struct \ref bufr_tableb where are stored all table B data
130 \param key descriptor string in format FXXYYY
131 \param code value to search in this table/flag
132 \return 0 if success, 1 otherwise
133*/
134int bufr_find_tableC_csv_index ( buf_t *index, struct bufr_tableC *tc, const char *key, uint32_t code )
135{
136 uint32_t ix;
137 buf_t i, i0;
138 char *c;
139 struct bufr_descriptor desc;
140
141 bufrdeco_assert ( tc != NULL && index != NULL );
142
143 ix = strtoul ( key, &c, 10 );
144 uint32_t_to_descriptor ( &desc, ix );
145 i0 = tc->x_start[desc.x];
146 for ( i = i0 ; i < i0 + tc->num[desc.x] ; i++ )
147 {
148 if ( tc->item[i].y == desc.y && tc->item[i].ival == code )
149 {
150 *index = i;
151 return 0; // found
152 }
153 }
154 return 1; // not found
155}
156
157/*!
158 \fn char * bufrdeco_explained_table_csv_val (char *expl, size_t dim, struct bufr_tableC *tc, struct bufr_descriptor *d, int ival)
159 \brief gets a string with the meaning of a value for a code table descriptor
160 \param expl string with resulting meaning
161 \param dim numero máximo de caracteres de la cadena resultante
162 \param tc pointer to a \ref bufr_tableC struct
163 \param index element to read if is not 0
164 \param d pointer to the source descriptor
165 \param ival integer value for the descriptor
166 \return If something went wrong, it returns NULL . Otherwise it returns \a expl
167*/
168char * bufrdeco_explained_table_val ( char *expl, size_t dim, struct bufr_tableC *tc, uint32_t *index, struct bufr_descriptor *d, uint32_t ival )
169{
170 buf_t i;
171
172 bufrdeco_assert ( tc != NULL && expl != NULL && index != NULL && d != NULL);
173
174 if ( bufr_find_tableC_csv_index ( &i, tc, d->c, ival ) )
175 {
176 return NULL; // descritor not found
177 }
178
179 // here the calling b item learn where to find first table C struct for a given x and y.
180 *index = tc->x_start[d->x] + tc->y_ref[d->x][d->y];
181
182 strncpy_safe ( expl, tc->item[i].description, dim );
183 return expl;
184}
185
186/*!
187 \fn char * bufrdeco_explained_flag_val(char *expl, size_t dim, struct bufr_descriptor *d, unsigned long ival, uint8_t nbits)
188 \brief gets a string with the meaning of a value for a flag table descriptor
189 \param expl string with resulting meaning
190 \param dim max length alowed for \a expl string
191 \param d pointer to the source descriptor
192 \param ival integer value for the descriptos
193 \param nbits uint8_t with the bit extensión of descriptor
194 \return If something went wrong, it returns NULL . Otherwise it returns \a expl
195
196 Remember that in FLAG tables for bufr, bit 1 is most significant and N the less one. Bit N only is set to
197 1 when all others are also set to one, i.e. in case of missing value.
198
199*/
200char * bufrdeco_explained_flag_val ( char *expl, size_t dim, struct bufr_tableC *tc, struct bufr_descriptor *d,
201 uint64_t ival, uint8_t nbits )
202{
203 size_t used = 0;
204 uint64_t test, test0;
205 uint64_t v;
206 size_t i, j;
207
208 bufrdeco_assert ( tc != NULL && expl != NULL && d != NULL);
209
210 if ( tc->num[d->x] == 0 )
211 {
212 //printf("Descriptor %s No encontrado\n", d->c);
213 return NULL;
214 }
215
216 // First line for descriptor
217 i = tc->x_start[d->x] + tc->y_ref[d->x][d->y];
218
219 // init description
220 expl[0] = '\0';
221
222 for ( j = 0, test0 = 1 ; j < nbits && ( tc->item[i].x == d->x ) && ( tc->item[i].y == d->y ) ; i++ )
223 {
224 v = tc->item[i].ival; // v is the bit number
225 j++;
226
227 // case 0 with meaning
228 if ( v == 0 )
229 {
230 test0 = 1;
231 if ( ival == 0 )
232 {
233 used += snprintf ( expl + used, dim - used, "|" );
234 used += snprintf ( expl + used, dim - used, "%s", tc->item[i].description );
235 return expl;
236 }
237 }
238
239 test = test0 << ( nbits - v );
240
241 if ( v && ( test & ival ) != 0 )
242 {
243 used += snprintf ( expl + used, dim - used, "|" );
244 used += snprintf ( expl + used, dim - used, "%s", tc->item[i].description );
245 }
246 else
247 {
248 continue;
249 }
250 //printf ( "%s\n", expl );
251 }
252 // if match then we have finished the search
253 return expl;
254}
Include header file for bufrdeco library.
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_EXPLAINED_LENGTH
Maximum length for a explained descriptor string.
Definition: bufrdeco.h:122
#define strncpy_safe(_target_, _src_, _dim_)
Macro to make safely a strcpy when we know in calling function the size of string target directly.
Definition: bufrdeco.h:366
int uint32_t_to_descriptor(struct bufr_descriptor *d, uint32_t id)
parse an integer with a descriptor fom bufr ECWMF libary
#define CSV_MAXL
Maximum length in a string to be parsed as csv.
Definition: bufrdeco.h:128
#define BUFR_MAXLINES_TABLEC
The maximum expected lines in a Table C file.
Definition: bufrdeco.h:96
int parse_csv_line(int *nt, char *tk[], char *lin)
Parse a csv line.
Definition: bufrdeco_csv.c:258
int bufr_read_tableC(struct bufrdeco *b)
Reads a file with table C content (Code table and bit flags) according with csv WMO format.
char * bufrdeco_explained_table_val(char *expl, size_t dim, struct bufr_tableC *tc, uint32_t *index, struct bufr_descriptor *d, uint32_t ival)
char * bufrdeco_explained_flag_val(char *expl, size_t dim, struct bufr_tableC *tc, struct bufr_descriptor *d, uint64_t ival, uint8_t nbits)
int bufr_find_tableC_csv_index(buf_t *index, struct bufr_tableC *tc, const char *key, uint32_t code)
BUFR descriptor.
Definition: bufrdeco.h:409
char c[12]
Definition: bufrdeco.h:414
char description[BUFR_EXPLAINED_LENGTH]
Definition: bufrdeco.h:882
Store a table C readed from a file formated and named as ECMWF bufrdc package.
Definition: bufrdeco.h:891
int wmo_table
Definition: bufrdeco.h:892
buf_t num[64]
Definition: bufrdeco.h:897
struct bufr_tableC_decoded_item item[BUFR_MAXLINES_TABLEC]
Definition: bufrdeco.h:899
char path[BUFRDECO_PATH_LENGTH]
Definition: bufrdeco.h:893
buf_t x_start[64]
Definition: bufrdeco.h:896
buf_t nlines
Definition: bufrdeco.h:895
char old_path[BUFRDECO_PATH_LENGTH]
Definition: bufrdeco.h:894
buf_t y_ref[64][256]
Definition: bufrdeco.h:898
struct bufr_tableC c
Definition: bufrdeco.h:940
This struct contains all needed data to parse and decode a BUFR file.
Definition: bufrdeco.h:965
struct bufr_tables * tables
Definition: bufrdeco.h:973
char error[1024]
Definition: bufrdeco.h:983