NCEPLIBS-g2c  1.8.0
g2cxml.c
Go to the documentation of this file.
1 
7 #include <libxml/tree.h>
8 #include <libxml/parser.h>
9 #include <grib2_int.h>
10 
12 xmlDocPtr doc;
13 
16 
21 void
23 {
25 
26  for (t = g2c_table; t; t = t->next)
27  {
29 
30  printf("%s\n", t->title);
31  for (e = t->entry; e; e = e->next)
32  printf("code %s desc %s status %s\n", e->code, e->desc, e->status);
33 
34  }
35 }
36 
41 void
43 {
44  G2C_CODE_TABLE_T *t, *the_next = NULL;
45 
46  /* If g2c_table is NULL, then tables have already been
47  * freed. */
48  if (!g2c_table)
49  return;
50 
51  /* Free each table. */
52  for (t = g2c_table; t; t = the_next)
53  {
55  G2C_CODE_ENTRY_T *e_next;
56 
57  /* Free each entry in the table. */
58  the_next = t->next;
59  for (e = t->entry; e; e = e_next)
60  {
61  e_next = e->next;
62  free(e);
63  }
64 
65  free(t);
66  }
67 
68  /* Set to NULL so we all know g2c_table has been freed. */
69  g2c_table = NULL;
70 }
71 
83 int
84 g2c_find_desc_str(char *title, char *code, char *desc)
85 {
86  G2C_CODE_TABLE_T *t = NULL;
87  int found = 0;
88 
89  /* Check inputs. */
90  if (!title || strlen(title) > G2C_MAX_GRIB_TITLE_LEN
91  || !code || strlen(code) > G2C_MAX_GRIB_CODE_LEN || !desc)
92  return G2C_EINVAL;
93 
94  /* Find table. */
95  for (t = g2c_table; !found && t; t = t->next)
96  {
97  if (!strncmp(title, t->title, strlen(title)))
98  {
99  G2C_CODE_ENTRY_T *e = NULL;
100 
101  /* Find entry. */
102  for (e = t->entry; e; e = e->next)
103  {
104  if (!strncmp(code, e->code, strlen(code)))
105  {
106  strcpy(desc, e->desc);
107  found++;
108  break;
109  }
110  }
111  }
112  }
113 
114  if (!found)
115  return G2C_ENOTFOUND;
116 
117  return G2C_NOERROR;
118 }
119 
131 int
132 g2c_find_desc(char *title, int code, char *desc)
133 {
134  char str_code[G2C_MAX_GRIB_CODE_LEN + 1];
135 
136  sprintf(str_code, "%d", code);
137  return g2c_find_desc_str(title, str_code, desc);
138 }
139 
149 g2c_find_table(char *key)
150 {
151  G2C_CODE_TABLE_T *g;
152 
153  for (g = g2c_table; g; g = g->next)
154  if (!strncmp(key, g->title, G2C_MAX_GRIB_TITLE_LEN))
155  return g;
156 
157  return NULL;
158 }
159 
170 g2c_find_entry(char *desc, G2C_CODE_TABLE_T *table)
171 {
172  G2C_CODE_ENTRY_T *e;
173 
174  for (e = table->entry; e; e = e->next)
175  if (!strncmp(desc, e->desc, G2C_MAX_GRIB_DESC_LEN))
176  return e;
177 
178  return NULL;
179 }
180 
189 int
191 {
192  xmlNode *cur;
193  xmlChar *key;
194  G2C_CODE_TABLE_T *my_table = NULL;
195  G2C_CODE_ENTRY_T *new_entry = NULL;
196 
197  /* If g2c_table is not NULL, then tables have already been
198  * initialized. */
199  if (g2c_table)
200  return G2C_NOERROR;
201 
202  /* Ingest the XML document. */
203  if (!(doc = xmlReadFile("CodeFlag.xml", NULL, 0)))
204  return G2C_EXML;
205 
206  /* Go through the document and save table data. */
207  cur = xmlDocGetRootElement(doc)->xmlChildrenNode;
208  while (cur)
209  {
210  xmlNode *child = cur->xmlChildrenNode;
211 
212  /* Each child at this level is a table of codes. */
213  while (child)
214  {
215  G2C_CODE_TABLE_T *new_table = NULL;
216 
217  if ((!xmlStrcmp(child->name, (const xmlChar *)"Title_en")))
218  {
219  key = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
220  if (strlen((char *)key) > G2C_MAX_GRIB_TITLE_LEN)
221  return G2C_ENAMETOOLONG;
222  if (!(my_table = g2c_find_table((char *)key)))
223  {
224  if (!(new_table = calloc(1, sizeof(G2C_CODE_TABLE_T))))
225  return G2C_ENOMEM;
226  strncpy(new_table->title, (char *)key, G2C_MAX_GRIB_TITLE_LEN);
227  /* printf("title: %s\n", key); */
228  my_table = new_table;
229  }
230  xmlFree(key);
231  }
232 
233  if (my_table)
234  {
235  if ((!xmlStrcmp(child->name, (const xmlChar *)"CodeFlag")))
236  {
237  G2C_CODE_ENTRY_T *e;
238 
239  if (!(new_entry = calloc(1, sizeof(G2C_CODE_ENTRY_T))))
240  return G2C_ENOMEM;
241  if (child->xmlChildrenNode)
242  {
243  key = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
244  if (strlen((char *)key) > G2C_MAX_GRIB_CODE_LEN)
245  return G2C_ENAMETOOLONG;
246  strncpy(new_entry->code, (char *)key, G2C_MAX_GRIB_CODE_LEN);
247  /* printf("code: %s\n", key); */
248  xmlFree(key);
249  }
250 
251  /* Add entry at end of list. */
252  if (my_table->entry)
253  {
254  for (e = my_table->entry; e->next; e = e->next)
255  ;
256  e->next = new_entry;
257  }
258  else
259  my_table->entry = new_entry;
260  }
261  if ((!xmlStrcmp(child->name, (const xmlChar *)"MeaningParameterDescription_en")))
262  {
263  key = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
264  if (strlen((char *)key) > G2C_MAX_GRIB_DESC_LEN)
265  return G2C_ENAMETOOLONG;
266  if (!new_entry)
267  return G2C_EXML;
268  strncpy(new_entry->desc, (char *)key, G2C_MAX_GRIB_DESC_LEN);
269  /* printf("description: %s\n", key); */
270  xmlFree(key);
271  }
272  if ((!xmlStrcmp(child->name, (const xmlChar *)"Status")))
273  {
274  key = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
275  if (strlen((char *)key) > G2C_MAX_GRIB_STATUS_LEN)
276  return G2C_ENAMETOOLONG;
277  if (!new_entry)
278  return G2C_EXML;
279  strncpy(new_entry->status, (char *)key, G2C_MAX_GRIB_STATUS_LEN);
280  /* printf("status: %s\n", key); */
281  xmlFree(key);
282  }
283  }
284 
285  /* Move to next node of XML document. */
286  child = child->next;
287 
288  /* Add this table to our list of GRIB tables. */
289  if (new_table)
290  {
291  if (!g2c_table)
292  g2c_table = new_table;
293  else
294  {
296 
297  /* Go to end of list and add the table. */
298  if (g)
299  {
300  for (; g->next; g = g->next)
301  ;
302  g->next = new_table;
303  }
304  else
305  {
306  g2c_table = new_table;
307  }
308  }
309  new_table = NULL;
310  }
311  }
312 
313  cur = cur->next;
314  }
315 
316  /* g2c_print_tables(); */
317 
318  xmlFreeDoc(doc);
319  xmlCleanupParser();
320 
321  return G2C_NOERROR;
322 }
int g2c_find_desc_str(char *title, char *code, char *desc)
Given a table title and a code, find a description.
Definition: g2cxml.c:84
int g2c_find_desc(char *title, int code, char *desc)
Given a table title and an integer code, find a description.
Definition: g2cxml.c:132
int g2c_xml_init()
Init.
Definition: g2cxml.c:190
G2C_CODE_ENTRY_T * g2c_find_entry(char *desc, G2C_CODE_TABLE_T *table)
Find an entry in a table given a description.
Definition: g2cxml.c:170
void g2c_free_tables()
Free table memory.
Definition: g2cxml.c:42
G2C_CODE_TABLE_T * g2c_find_table(char *key)
Find a table given a key.
Definition: g2cxml.c:149
xmlDocPtr doc
Contains the parsed XML document.
Definition: g2cxml.c:12
G2C_CODE_TABLE_T * g2c_table
Pointer to the list of code tables.
Definition: g2cxml.c:15
void g2c_print_tables()
Print the table data.
Definition: g2cxml.c:22
#define G2C_MAX_GRIB_TITLE_LEN
Maximum length of code table title.
Definition: grib2.h:428
#define G2C_MAX_GRIB_DESC_LEN
Maximum length of code description.
Definition: grib2.h:424
#define G2C_ENAMETOOLONG
Name too long.
Definition: grib2.h:495
#define G2C_ENOMEM
Out of memory.
Definition: grib2.h:500
#define G2C_ENOTFOUND
Table or entry not found.
Definition: grib2.h:504
#define G2C_MAX_GRIB_STATUS_LEN
Maximum length of code status.
Definition: grib2.h:425
#define G2C_EINVAL
Invalid input.
Definition: grib2.h:496
#define G2C_MAX_GRIB_CODE_LEN
Maximum length of code.
Definition: grib2.h:427
#define G2C_EXML
XML error.
Definition: grib2.h:503
#define G2C_NOERROR
No error.
Definition: grib2.h:491
Header file with internal function prototypes NCEPLIBS-g2c library.
A GRIB2 code table.
Definition: grib2_int.h:255
An entry in a GRIB2 code table.
Definition: grib2_int.h:246