NCEPLIBS-bufr  12.0.1
cfe.c
Go to the documentation of this file.
1 
8 #include "bufrlib.h"
9 
11 #define MAX_MEANING_LEN 150
12 
16 struct code_flag_entry {
18  int iffxyn;
20  int ifval;
22  char ifmeaning[MAX_MEANING_LEN+1];
26  int iffxynd;
30  int ifvald;
31 };
32 
34 struct code_flag_entry *cfe; /* will automatically initialize to NULL */
35 
41 int mxmtbf;
42 
44 int nmtf;
45 
55 void
56 inittbf(void)
57 {
58  char brtstr[50] = "BUFRLIB: INITTBF FAILED ALLOCATING CFE";
59 
60  /*
61  ** Has array space for the internal memory structure been
62  ** allocated yet?
63  */
64  if ( cfe == NULL ) {
65 
66  mxmtbf = igetprm_f("MXMTBF");
67 
68  if ( ( cfe = malloc(mxmtbf * sizeof(struct code_flag_entry)) ) == NULL ) {
69  bort_f(brtstr);
70  }
71  }
72 
73  nmtf = 0;
74 }
75 
84 void
85 dlloctbf(void)
86 {
87  free(cfe);
88 
89  cfe = NULL;
90 }
91 
112 int
113 cmpstia1(const void *pe1, const void *pe2)
114 {
115  struct code_flag_entry *mype1 = ( struct code_flag_entry * ) pe1;
116  struct code_flag_entry *mype2 = ( struct code_flag_entry * ) pe2;
117 
118  if ( mype1->iffxyn == mype2->iffxyn ) {
119  if ( mype1->ifval == mype2->ifval ) {
120  if ( mype1->iffxynd == mype2->iffxynd ) {
121  if ( mype1->ifvald == mype2->ifvald ) return 0;
122  return ( mype1->ifvald < mype2->ifvald ? -1 : 1 );
123  }
124  else {
125  return ( mype1->iffxynd < mype2->iffxynd ? -1 : 1 );
126  }
127  }
128  else {
129  return ( mype1->ifval < mype2->ifval ? -1 : 1 );
130  }
131  }
132  else {
133  return ( mype1->iffxyn < mype2->iffxyn ? -1 : 1 );
134  }
135 }
136 
157 int
158 cmpstia2(const void *pe1, const void *pe2)
159 {
160  struct code_flag_entry *mype1 = ( struct code_flag_entry * ) pe1;
161  struct code_flag_entry *mype2 = ( struct code_flag_entry * ) pe2;
162 
163  if ( mype1->iffxyn == mype2->iffxyn ) {
164  if ( mype1->ifval == mype2->ifval ) return 0;
165  return ( mype1->ifval < mype2->ifval ? -1 : 1 );
166  }
167  else {
168  return ( mype1->iffxyn < mype2->iffxyn ? -1 : 1 );
169  }
170 }
171 
190 void
191 strtbfe(int ifxyn, int ival, char *meaning, int lmeaning, int idfxy, int idval)
192 {
193  unsigned int mnlen;
194 
195  static char brtstr[50] = "BUFRLIB: STRTBFE - MXMTBF OVERFLOW";
196 
197  /*
198  ** Confirm that there's room for another entry in the structure.
199  */
200  if ( nmtf >= mxmtbf ) bort_f(brtstr);
201 
202  /*
203  ** Store the new entry.
204  */
205  cfe[nmtf].iffxyn = ifxyn;
206  cfe[nmtf].ifval = ival;
207  mnlen = ( lmeaning > MAX_MEANING_LEN ? MAX_MEANING_LEN : lmeaning );
208  strncpy(&cfe[nmtf].ifmeaning[0], meaning, mnlen);
209  cfe[nmtf].ifmeaning[mnlen] = '\0';
210  cfe[nmtf].iffxynd = idfxy;
211  cfe[nmtf].ifvald = idval;
212  nmtf++;
213 }
214 
224 void
225 sorttbf(void)
226 {
227  qsort(&cfe[0], (size_t) nmtf, sizeof(struct code_flag_entry),
228  (int (*) (const void *, const void *)) cmpstia1);
229 }
230 
277 void
278 srchtbf(int ifxyi, int ivali, int *ifxyd, int mxfxyd, int ivald,
279  char *meaning, int mxmng, int *lnmng, int *iret)
280 {
281  struct code_flag_entry key, *pkey, *pcfe, *pbs;
282 
283  int ipt, ii, slmng;
284 
285  *iret = -1;
286 
287  /*
288  ** Initialize some values for searching the internal table.
289  */
290  key.iffxyn = ifxyi;
291  key.ifval = ivali;
292  key.iffxynd = ifxyd[0];
293  key.ifvald = ivald;
294 
295  pkey = &key;
296  pcfe = &cfe[0];
297 
298  /*
299  ** Search for a matching entry.
300  */
301  pbs = (struct code_flag_entry *) bsearch(pkey, pcfe, (size_t) nmtf,
302  sizeof(struct code_flag_entry),
303  (int (*) (const void *, const void *)) cmpstia1);
304  if ( pbs != NULL ) {
305  /*
306  ** A matching entry was found, so set the appropriate output
307  ** values and return.
308  */
309  ipt = pbs - pcfe;
310  slmng = strlen(cfe[ipt].ifmeaning);
311  *lnmng = ( mxmng > slmng ? slmng : mxmng );
312  strncpy(meaning, &cfe[ipt].ifmeaning[0], *lnmng);
313  *iret = 0;
314  return;
315  }
316 
317  /*
318  ** Was a particular dependency specified in the input?
319  */
320  if ( key.iffxynd != -1 ) {
321  /*
322  ** YES, so there's nothing else to do.
323  */
324  return;
325  }
326 
327  /*
328  ** NO, so check whether the given Table B descriptor and value have any
329  ** dependencies, and if so then return a list of those dependencies.
330  */
331  pbs = (struct code_flag_entry *) bsearch(pkey, pcfe, (size_t) nmtf,
332  sizeof(struct code_flag_entry),
333  (int (*) (const void *, const void *)) cmpstia2);
334  if ( pbs == NULL ) {
335  /*
336  ** There are no dependencies.
337  */
338  return;
339  }
340 
341  /*
342  ** Store the dependency that was returned by the secondary search.
343  ** However, there may be others within the internal table, so we'll
344  ** also need to check for those.
345  */
346  ipt = pbs - pcfe;
347  *iret = 0;
348  ifxyd[(*iret)++] = cfe[ipt].iffxynd;
349 
350  /*
351  ** Since the internal table is sorted, check immediately before and
352  ** after the returned dependency for any additional table entries which
353  ** correspond to the same Table B descriptor and value, but for which the
354  ** dependency is different. If any such additional dependencies are
355  ** found, return those as well.
356  */
357  ii = ipt - 1;
358  while ( ( ii >= 0 ) &&
359  ( *iret < mxfxyd ) &&
360  ( cfe[ii].iffxyn == key.iffxyn ) &&
361  ( cfe[ii].ifval == key.ifval ) ) {
362  if ( cfe[ii].iffxynd < ifxyd[(*iret)-1] )
363  ifxyd[(*iret)++] = cfe[ii].iffxynd;
364  ii--;
365  }
366  ii = ipt + 1;
367  while ( ( ii < nmtf ) &&
368  ( *iret < mxfxyd ) &&
369  ( cfe[ii].iffxyn == key.iffxyn ) &&
370  ( cfe[ii].ifval == key.ifval ) ) {
371  if ( ( cfe[ii].iffxynd > ifxyd[(*iret)-1] ) &&
372  ( cfe[ii].iffxynd > cfe[ipt].iffxynd ) )
373  ifxyd[(*iret)++] = cfe[ii].iffxynd;
374  ii++;
375  }
376 
377  return;
378 }
int igetprm_f(char *cprmnm)
Get the current value of a parameter.
Enable a number of NCEPLIBS-bufr subprograms to be called from within the C part of the library.
void bort_f(char *errstr)
Log one error message and abort application program.
void dlloctbf(void)
Free all dynamically-allocated memory for internal storage of master Code/Flag table entries.
Definition: cfe.c:85
int cmpstia2(const void *pe1, const void *pe2)
Define a comparison between two master Code/Flag table entries.
Definition: cfe.c:158
#define MAX_MEANING_LEN
Maximum length of a meaning string for a Code/Flag table entry.
Definition: cfe.c:11
int cmpstia1(const void *pe1, const void *pe2)
Define a comparison between two master Code/Flag table entries.
Definition: cfe.c:113
void inittbf(void)
Initialize memory for internal storage of master Code/Flag table entries.
Definition: cfe.c:56
void srchtbf(int ifxyi, int ivali, int *ifxyd, int mxfxyd, int ivald, char *meaning, int mxmng, int *lnmng, int *iret)
Search for a specified master Code/Flag table entry.
Definition: cfe.c:278
struct code_flag_entry * cfe
Master Code/Flag table entries.
Definition: cfe.c:34
int mxmtbf
Maximum number of master Code/Flag table entries, counting across all individual Code/Flag tables,...
Definition: cfe.c:41
void strtbfe(int ifxyn, int ival, char *meaning, int lmeaning, int idfxy, int idval)
Store a new master Code/Flag table entry.
Definition: cfe.c:191
int nmtf
Number of stored master Code/Flag table entries in cfe, up to a maximum of MXMTBF.
Definition: cfe.c:44
void sorttbf(void)
Sort entries within the master Code/Flag table.
Definition: cfe.c:225
integer(8), dimension(:), allocatable ival
BUFR data subset values.