Imported Upstream version 1.5.1
[routino] / src / tagging.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/tagging.c,v 1.5 2010/09/17 17:40:41 amb Exp $
3
4  Load the tagging rules from a file and the functions for handling them.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2010 Andrew M. Bishop
9
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Affero General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU Affero General Public License for more details.
19
20  You should have received a copy of the GNU Affero General Public License
21  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  ***************************************/
23
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include "files.h"
30 #include "tagging.h"
31 #include "xmlparse.h"
32
33
34 /* Global variables */
35
36 TaggingRuleList NodeRules={NULL,0};
37 TaggingRuleList WayRules={NULL,0};
38 TaggingRuleList RelationRules={NULL,0};
39
40
41 /* Local variables */
42
43 TaggingRuleList *current_list=NULL;
44 TaggingRule     *current_rule=NULL;
45
46
47 /* Local functions */
48
49 static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output);
50
51
52 /* The XML tag processing function prototypes */
53
54 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
55 //static int RoutinoTaggingType_function(const char *_tag_,int _type_);
56 static int WayType_function(const char *_tag_,int _type_);
57 static int NodeType_function(const char *_tag_,int _type_);
58 static int RelationType_function(const char *_tag_,int _type_);
59 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v);
60 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v);
61 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v);
62
63
64 /* The XML tag definitions */
65
66 /*+ The SetType type tag. +*/
67 static xmltag SetType_tag=
68               {"set",
69                2, {"k","v"},
70                SetType_function,
71                {NULL}};
72
73 /*+ The OutputType type tag. +*/
74 static xmltag OutputType_tag=
75               {"output",
76                2, {"k","v"},
77                OutputType_function,
78                {NULL}};
79
80 /*+ The IfType type tag. +*/
81 static xmltag IfType_tag=
82               {"if",
83                2, {"k","v"},
84                IfType_function,
85                {&SetType_tag,&OutputType_tag,NULL}};
86
87 /*+ The RelationType type tag. +*/
88 static xmltag RelationType_tag=
89               {"relation",
90                0, {NULL},
91                RelationType_function,
92                {&IfType_tag,NULL}};
93
94 /*+ The NodeType type tag. +*/
95 static xmltag NodeType_tag=
96               {"node",
97                0, {NULL},
98                NodeType_function,
99                {&IfType_tag,NULL}};
100
101 /*+ The WayType type tag. +*/
102 static xmltag WayType_tag=
103               {"way",
104                0, {NULL},
105                WayType_function,
106                {&IfType_tag,NULL}};
107
108 /*+ The RoutinoTaggingType type tag. +*/
109 static xmltag RoutinoTaggingType_tag=
110               {"routino-tagging",
111                0, {NULL},
112                NULL,
113                {&NodeType_tag,&WayType_tag,&RelationType_tag,NULL}};
114
115 /*+ The xmlDeclaration type tag. +*/
116 static xmltag xmlDeclaration_tag=
117               {"xml",
118                2, {"version","encoding"},
119                NULL,
120                {NULL}};
121
122
123 /*+ The complete set of tags at the top level. +*/
124 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoTaggingType_tag,NULL};
125
126
127 /* The XML tag processing functions */
128
129
130 /*++++++++++++++++++++++++++++++++++++++
131   The function that is called when the SetType XSD type is seen
132
133   int SetType_function Returns 0 if no error occured or something else otherwise.
134
135   const char *_tag_ Set to the name of the element tag that triggered this function call.
136
137   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
138
139   const char *k The contents of the 'k' attribute (or NULL if not defined).
140
141   const char *v The contents of the 'v' attribute (or NULL if not defined).
142   ++++++++++++++++++++++++++++++++++++++*/
143
144 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v)
145 {
146  if(_type_&XMLPARSE_TAG_START)
147     AppendTaggingAction(current_rule,k,v,0);
148
149  return(0);
150 }
151
152
153 /*++++++++++++++++++++++++++++++++++++++
154   The function that is called when the OutputType XSD type is seen
155
156   int OutputType_function Returns 0 if no error occured or something else otherwise.
157
158   const char *_tag_ Set to the name of the element tag that triggered this function call.
159
160   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
161
162   const char *k The contents of the 'k' attribute (or NULL if not defined).
163
164   const char *v The contents of the 'v' attribute (or NULL if not defined).
165   ++++++++++++++++++++++++++++++++++++++*/
166
167 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v)
168 {
169  if(_type_&XMLPARSE_TAG_START)
170     AppendTaggingAction(current_rule,k,v,1);
171
172  return(0);
173 }
174
175
176 /*++++++++++++++++++++++++++++++++++++++
177   The function that is called when the IfType XSD type is seen
178
179   int IfType_function Returns 0 if no error occured or something else otherwise.
180
181   const char *_tag_ Set to the name of the element tag that triggered this function call.
182
183   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
184
185   const char *k The contents of the 'k' attribute (or NULL if not defined).
186
187   const char *v The contents of the 'v' attribute (or NULL if not defined).
188   ++++++++++++++++++++++++++++++++++++++*/
189
190 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v)
191 {
192  if(_type_&XMLPARSE_TAG_START)
193    {
194     current_rule=AppendTaggingRule(current_list,k,v);
195    }
196
197  return(0);
198 }
199
200
201 /*++++++++++++++++++++++++++++++++++++++
202   The function that is called when the RelationType XSD type is seen
203
204   int RelationType_function Returns 0 if no error occured or something else otherwise.
205
206   const char *_tag_ Set to the name of the element tag that triggered this function call.
207
208   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
209   ++++++++++++++++++++++++++++++++++++++*/
210
211 static int RelationType_function(const char *_tag_,int _type_)
212 {
213  if(_type_&XMLPARSE_TAG_START)
214     current_list=&RelationRules;
215
216  return(0);
217 }
218
219
220 /*++++++++++++++++++++++++++++++++++++++
221   The function that is called when the NodeType XSD type is seen
222
223   int NodeType_function Returns 0 if no error occured or something else otherwise.
224
225   const char *_tag_ Set to the name of the element tag that triggered this function call.
226
227   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
228   ++++++++++++++++++++++++++++++++++++++*/
229
230 static int NodeType_function(const char *_tag_,int _type_)
231 {
232  if(_type_&XMLPARSE_TAG_START)
233     current_list=&NodeRules;
234
235  return(0);
236 }
237
238
239 /*++++++++++++++++++++++++++++++++++++++
240   The function that is called when the WayType XSD type is seen
241
242   int WayType_function Returns 0 if no error occured or something else otherwise.
243
244   const char *_tag_ Set to the name of the element tag that triggered this function call.
245
246   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
247   ++++++++++++++++++++++++++++++++++++++*/
248
249 static int WayType_function(const char *_tag_,int _type_)
250 {
251  if(_type_&XMLPARSE_TAG_START)
252     current_list=&WayRules;
253
254  return(0);
255 }
256
257
258 /*++++++++++++++++++++++++++++++++++++++
259   The function that is called when the RoutinoTaggingType XSD type is seen
260
261   int RoutinoTaggingType_function Returns 0 if no error occured or something else otherwise.
262
263   const char *_tag_ Set to the name of the element tag that triggered this function call.
264
265   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
266   ++++++++++++++++++++++++++++++++++++++*/
267
268 //static int RoutinoTaggingType_function(const char *_tag_,int _type_)
269 //{
270 // return(0);
271 //}
272
273
274 /*++++++++++++++++++++++++++++++++++++++
275   The function that is called when the XML declaration is seen
276
277   int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
278
279   const char *_tag_ Set to the name of the element tag that triggered this function call.
280
281   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
282
283   const char *version The contents of the 'version' attribute (or NULL if not defined).
284
285   const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
286   ++++++++++++++++++++++++++++++++++++++*/
287
288 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
289 //{
290 // return(0);
291 //}
292
293
294 /*++++++++++++++++++++++++++++++++++++++
295   The XML tagging rules parser.
296
297   int ParseXMLTaggingRules Returns 0 if OK or something else in case of an error.
298
299   const char *filename The name of the file to read.
300   ++++++++++++++++++++++++++++++++++++++*/
301
302 int ParseXMLTaggingRules(const char *filename)
303 {
304  int retval;
305
306  if(!ExistsFile(filename))
307    {
308     fprintf(stderr,"Error: Specified tagging rules file '%s' does not exist.\n",filename);
309     return(1);
310    }
311
312  FILE *file=fopen(filename,"r");
313
314  if(!file)
315    {
316     fprintf(stderr,"Error: Cannot open tagging rules file '%s' for reading.\n",filename);
317     return(1);
318    }
319
320  retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME);
321
322  fclose(file);
323
324  if(retval)
325     return(1);
326
327  return(0);
328 }
329
330
331 /*++++++++++++++++++++++++++++++++++++++
332   Append a tagging rule to the list of rules.
333
334   TaggingRule *AppendTaggingRule Returns the latest rule (the just added one).
335
336   TaggingRuleList *rules The list of rules to add to.
337
338   const char *k The tag key.
339
340   const char *v The tag value.
341   ++++++++++++++++++++++++++++++++++++++*/
342
343 TaggingRule *AppendTaggingRule(TaggingRuleList *rules,const char *k,const char *v)
344 {
345  if((rules->nrules%16)==0)
346     rules->rules=(TaggingRule*)realloc((void*)rules->rules,(rules->nrules+16)*sizeof(TaggingRule));
347
348  rules->nrules++;
349
350  if(k)
351     rules->rules[rules->nrules-1].k=strcpy(malloc(strlen(k)+1),k);
352  else
353     rules->rules[rules->nrules-1].k=NULL;
354
355  if(v)
356     rules->rules[rules->nrules-1].v=strcpy(malloc(strlen(v)+1),v);
357  else
358     rules->rules[rules->nrules-1].v=NULL;
359
360  rules->rules[rules->nrules-1].nactions=0;
361  rules->rules[rules->nrules-1].actions=NULL;
362
363  return(&rules->rules[rules->nrules-1]);
364 }
365
366
367 /*++++++++++++++++++++++++++++++++++++++
368   Append a tagging action to a tagging rule.
369
370   TaggingRule *rule The rule to add the action to.
371
372   const char *k The tag key.
373
374   const char *v The tag value.
375
376   int output Set to 1 if this is an output rule.
377   ++++++++++++++++++++++++++++++++++++++*/
378
379 void AppendTaggingAction(TaggingRule *rule,const char *k,const char *v,int output)
380 {
381  if((rule->nactions%16)==0)
382     rule->actions=(TaggingAction*)realloc((void*)rule->actions,(rule->nactions+16)*sizeof(TaggingAction));
383
384  rule->nactions++;
385
386  rule->actions[rule->nactions-1].output=output;
387
388  if(k)
389     rule->actions[rule->nactions-1].k=strcpy(malloc(strlen(k)+1),k);
390  else
391     rule->actions[rule->nactions-1].k=NULL;
392
393  if(v)
394     rule->actions[rule->nactions-1].v=strcpy(malloc(strlen(v)+1),v);
395  else
396     rule->actions[rule->nactions-1].v=NULL;
397 }
398
399
400 /*++++++++++++++++++++++++++++++++++++++
401   Create a new TagList structure.
402
403   TagList *NewTagList Returns the new allocated TagList.
404   ++++++++++++++++++++++++++++++++++++++*/
405
406 TagList *NewTagList(void)
407 {
408  return((TagList*)calloc(sizeof(TagList),1));
409 }
410
411
412 /*++++++++++++++++++++++++++++++++++++++
413   Append a tag to the list of tags.
414
415   TagList *tags The list of tags to add to.
416
417   const char *k The tag key.
418
419   const char *v The tag value.
420   ++++++++++++++++++++++++++++++++++++++*/
421
422 void AppendTag(TagList *tags,const char *k,const char *v)
423 {
424  if((tags->ntags%16)==0)
425    {
426     int i;
427
428     tags->k=(char**)realloc((void*)tags->k,(tags->ntags+16)*sizeof(char*));
429     tags->v=(char**)realloc((void*)tags->v,(tags->ntags+16)*sizeof(char*));
430
431     for(i=tags->ntags;i<(tags->ntags+16);i++)
432        tags->k[i]=tags->v[i]=NULL;
433    }
434
435  tags->k[tags->ntags]=strcpy(realloc(tags->k[tags->ntags],strlen(k)+1),k);
436  tags->v[tags->ntags]=strcpy(realloc(tags->v[tags->ntags],strlen(v)+1),v);
437
438  tags->ntags++;
439 }
440
441
442 /*++++++++++++++++++++++++++++++++++++++
443   Modify an existing tag or append a new tag to the list of tags.
444
445   TagList *tags The list of tags to modify.
446
447   const char *k The tag key.
448
449   const char *v The tag value.
450   ++++++++++++++++++++++++++++++++++++++*/
451
452 void ModifyTag(TagList *tags,const char *k,const char *v)
453 {
454  int i;
455
456  for(i=0;i<tags->ntags;i++)
457     if(!strcmp(tags->k[i],k))
458       {
459        tags->v[i]=strcpy(realloc(tags->v[i],strlen(v)+1),v);
460        return;
461       }
462
463  AppendTag(tags,k,v);
464 }
465
466
467 /*++++++++++++++++++++++++++++++++++++++
468   Delete a tag list and the contents.
469
470   TagList *tags The list of tags to delete.
471   ++++++++++++++++++++++++++++++++++++++*/
472
473 void DeleteTagList(TagList *tags)
474 {
475  int i;
476
477  for(i=0;i<tags->ntags;i++)
478    {
479     if(tags->k[i]) free(tags->k[i]);
480     if(tags->v[i]) free(tags->v[i]);
481    }
482
483  if(tags->ntags)
484    {
485     free(tags->k);
486     free(tags->v);
487    }
488
489  free(tags);
490 }
491
492
493 /*++++++++++++++++++++++++++++++++++++++
494   Apply a set of tagging rules to a set of tags.
495
496   TagList *ApplyTaggingRules Returns the list of output tags after modification.
497
498   TaggingRuleList *rules The tagging rules to apply.
499
500   TagList *tags The tags to be modified.
501   ++++++++++++++++++++++++++++++++++++++*/
502
503 TagList *ApplyTaggingRules(TaggingRuleList *rules,TagList *tags)
504 {
505  TagList *result=NewTagList();
506  int i,j;
507
508  for(i=0;i<rules->nrules;i++)
509    {
510     if(rules->rules[i].k && rules->rules[i].v)
511       {
512        for(j=0;j<tags->ntags;j++)
513           if(!strcmp(tags->k[j],rules->rules[i].k) && !strcmp(tags->v[j],rules->rules[i].v))
514              apply_actions(&rules->rules[i],j,tags,result);
515       }
516     else if(rules->rules[i].k && !rules->rules[i].v)
517       {
518        for(j=0;j<tags->ntags;j++)
519           if(!strcmp(tags->k[j],rules->rules[i].k))
520              apply_actions(&rules->rules[i],j,tags,result);
521       }
522     else if(!rules->rules[i].k && rules->rules[i].v)
523       {
524        for(j=0;j<tags->ntags;j++)
525           if(!strcmp(tags->v[j],rules->rules[i].v))
526              apply_actions(&rules->rules[i],j,tags,result);
527       }
528     else /* if(!rules->rules[i].k && !rules->rules[i].v) */
529       {
530        for(j=0;j<tags->ntags;j++)
531           apply_actions(&rules->rules[i],j,tags,result);
532       }
533    }
534
535  return(result);
536 }
537
538
539 /*++++++++++++++++++++++++++++++++++++++
540   Apply a set of actions to a matching tag.
541
542   TaggingRule *rule The rule that matched (containing the actions).
543
544   int match The matching tag number.
545
546   TagList *input The input tags.
547
548   TagList *output The output tags.
549   ++++++++++++++++++++++++++++++++++++++*/
550
551 static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output)
552 {
553  int i;
554  
555  for(i=0;i<rule->nactions;i++)
556    {
557     char *k,*v;
558
559     if(rule->actions[i].k)
560        k=rule->actions[i].k;
561     else
562        k=input->k[match];
563
564     if(rule->actions[i].v)
565        v=rule->actions[i].v;
566     else
567        v=input->v[match];
568
569     if(rule->actions[i].output)
570        ModifyTag(output,k,v);
571     else
572        ModifyTag(input,k,v);
573    }
574 }