NCEPLIBS-bufr  12.1.0
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 
52 void
53 inittbf(void)
54 {
55  char brtstr[50] = "BUFRLIB: INITTBF FAILED ALLOCATING CFE";
56 
57  /*
58  ** Has array space for the internal memory structure been
59  ** allocated yet?
60  */
61  if ( cfe == NULL ) {
62 
63  mxmtbf = igetprm_f("MXMTBF");
64 
65  if ( ( cfe = malloc(mxmtbf * sizeof(struct code_flag_entry)) ) == NULL ) {
66  bort_f(brtstr);
67  }
68  }
69 
70  nmtf = 0;
71 }
72 
80 void
81 dlloctbf(void)
82 {
83  free(cfe);
84 
85  cfe = NULL;
86 }
87 
106 int
107 cmpstia1(const void *pe1, const void *pe2)
108 {
109  struct code_flag_entry *mype1 = ( struct code_flag_entry * ) pe1;
110  struct code_flag_entry *mype2 = ( struct code_flag_entry * ) pe2;
111 
112  if ( mype1->iffxyn == mype2->iffxyn ) {
113  if ( mype1->ifval == mype2->ifval ) {
114  if ( mype1->iffxynd == mype2->iffxynd ) {
115  if ( mype1->ifvald == mype2->ifvald ) return 0;
116  return ( mype1->ifvald < mype2->ifvald ? -1 : 1 );
117  }
118  else {
119  return ( mype1->iffxynd < mype2->iffxynd ? -1 : 1 );
120  }
121  }
122  else {
123  return ( mype1->ifval < mype2->ifval ? -1 : 1 );
124  }
125  }
126  else {
127  return ( mype1->iffxyn < mype2->iffxyn ? -1 : 1 );
128  }
129 }
130 
149 int
150 cmpstia2(const void *pe1, const void *pe2)
151 {
152  struct code_flag_entry *mype1 = ( struct code_flag_entry * ) pe1;
153  struct code_flag_entry *mype2 = ( struct code_flag_entry * ) pe2;
154 
155  if ( mype1->iffxyn == mype2->iffxyn ) {
156  if ( mype1->ifval == mype2->ifval ) return 0;
157  return ( mype1->ifval < mype2->ifval ? -1 : 1 );
158  }
159  else {
160  return ( mype1->iffxyn < mype2->iffxyn ? -1 : 1 );
161  }
162 }
163 
179 void
180 strtbfe(int ifxyn, int ival, char *meaning, int lmeaning, int idfxy, int idval)
181 {
182  unsigned int mnlen;
183 
184  static char brtstr[50] = "BUFRLIB: STRTBFE - MXMTBF OVERFLOW";
185 
186  /*
187  ** Confirm that there's room for another entry in the structure.
188  */
189  if ( nmtf >= mxmtbf ) bort_f(brtstr);
190 
191  /*
192  ** Store the new entry.
193  */
194  cfe[nmtf].iffxyn = ifxyn;
195  cfe[nmtf].ifval = ival;
196  mnlen = ( lmeaning > MAX_MEANING_LEN ? MAX_MEANING_LEN : lmeaning );
197  strncpy(&cfe[nmtf].ifmeaning[0], meaning, mnlen);
198  cfe[nmtf].ifmeaning[mnlen] = '\0';
199  cfe[nmtf].iffxynd = idfxy;
200  cfe[nmtf].ifvald = idval;
201  nmtf++;
202 }
203 
210 void
211 sorttbf(void)
212 {
213  qsort(&cfe[0], (size_t) nmtf, sizeof(struct code_flag_entry),
214  (int (*) (const void *, const void *)) cmpstia1);
215 }
216 
263 void
264 srchtbf(int ifxyi, int ivali, int *ifxyd, int mxfxyd, int ivald,
265  char *meaning, int mxmng, int *lnmng, int *iret)
266 {
267  struct code_flag_entry key, *pkey, *pcfe, *pbs;
268 
269  int ipt, ii, slmng;
270 
271  *iret = -1;
272 
273  /*
274  ** Initialize some values for searching the internal table.
275  */
276  key.iffxyn = ifxyi;
277  key.ifval = ivali;
278  key.iffxynd = ifxyd[0];
279  key.ifvald = ivald;
280 
281  pkey = &key;
282  pcfe = &cfe[0];
283 
284  /*
285  ** Search for a matching entry.
286  */
287  pbs = (struct code_flag_entry *) bsearch(pkey, pcfe, (size_t) nmtf,
288  sizeof(struct code_flag_entry),
289  (int (*) (const void *, const void *)) cmpstia1);
290  if ( pbs != NULL ) {
291  /*
292  ** A matching entry was found, so set the appropriate output
293  ** values and return.
294  */
295  ipt = pbs - pcfe;
296  slmng = strlen(cfe[ipt].ifmeaning);
297  *lnmng = ( mxmng > slmng ? slmng : mxmng );
298  strncpy(meaning, &cfe[ipt].ifmeaning[0], *lnmng);
299  *iret = 0;
300  return;
301  }
302 
303  /*
304  ** Was a particular dependency specified in the input?
305  */
306  if ( key.iffxynd != -1 ) {
307  /*
308  ** YES, so there's nothing else to do.
309  */
310  return;
311  }
312 
313  /*
314  ** NO, so check whether the given Table B descriptor and value have any
315  ** dependencies, and if so then return a list of those dependencies.
316  */
317  pbs = (struct code_flag_entry *) bsearch(pkey, pcfe, (size_t) nmtf,
318  sizeof(struct code_flag_entry),
319  (int (*) (const void *, const void *)) cmpstia2);
320  if ( pbs == NULL ) {
321  /*
322  ** There are no dependencies.
323  */
324  return;
325  }
326 
327  /*
328  ** Store the dependency that was returned by the secondary search.
329  ** However, there may be others within the internal table, so we'll
330  ** also need to check for those.
331  */
332  ipt = pbs - pcfe;
333  *iret = 0;
334  ifxyd[(*iret)++] = cfe[ipt].iffxynd;
335 
336  /*
337  ** Since the internal table is sorted, check immediately before and
338  ** after the returned dependency for any additional table entries which
339  ** correspond to the same Table B descriptor and value, but for which the
340  ** dependency is different. If any such additional dependencies are
341  ** found, return those as well.
342  */
343  ii = ipt - 1;
344  while ( ( ii >= 0 ) &&
345  ( *iret < mxfxyd ) &&
346  ( cfe[ii].iffxyn == key.iffxyn ) &&
347  ( cfe[ii].ifval == key.ifval ) ) {
348  if ( cfe[ii].iffxynd < ifxyd[(*iret)-1] )
349  ifxyd[(*iret)++] = cfe[ii].iffxynd;
350  ii--;
351  }
352  ii = ipt + 1;
353  while ( ( ii < nmtf ) &&
354  ( *iret < mxfxyd ) &&
355  ( cfe[ii].iffxyn == key.iffxyn ) &&
356  ( cfe[ii].ifval == key.ifval ) ) {
357  if ( ( cfe[ii].iffxynd > ifxyd[(*iret)-1] ) &&
358  ( cfe[ii].iffxynd > cfe[ipt].iffxynd ) )
359  ifxyd[(*iret)++] = cfe[ii].iffxynd;
360  ii++;
361  }
362 
363  return;
364 }
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:81
int cmpstia2(const void *pe1, const void *pe2)
Define a comparison between two master Code/Flag table entries.
Definition: cfe.c:150
#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:107
void inittbf(void)
Initialize memory for internal storage of master Code/Flag table entries, including dynamically alloc...
Definition: cfe.c:53
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:264
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:180
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, in preparation for future searches using function src...
Definition: cfe.c:211
integer *8, dimension(:), allocatable ival
BUFR data subset values.