Imported Upstream version 1.4.1
[routino] / src / tagging.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/tagging.c,v 1.2 2010/05/23 10:18:59 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 "functions.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 IfType_function(const char *_tag_,int _type_,const char *k,const char *v);
58 static int RelationType_function(const char *_tag_,int _type_);
59 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v);
60 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v);
61 static int NodeType_function(const char *_tag_,int _type_);
62
63
64 /* The XML tag definitions */
65
66 /*+ The NodeType type tag. +*/
67 static xmltag NodeType_tag=
68               {"node",
69                0, {NULL},
70                NodeType_function,
71                {NULL}};
72
73 /*+ The SetType type tag. +*/
74 static xmltag SetType_tag=
75               {"set",
76                2, {"k","v"},
77                SetType_function,
78                {NULL}};
79
80 /*+ The OutputType type tag. +*/
81 static xmltag OutputType_tag=
82               {"output",
83                2, {"k","v"},
84                OutputType_function,
85                {NULL}};
86
87 /*+ The RelationType type tag. +*/
88 static xmltag RelationType_tag=
89               {"relation",
90                0, {NULL},
91                RelationType_function,
92                {NULL}};
93
94 /*+ The IfType type tag. +*/
95 static xmltag IfType_tag=
96               {"if",
97                2, {"k","v"},
98                IfType_function,
99                {&SetType_tag,&OutputType_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 NodeType XSD type is seen
132
133   int NodeType_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
140 static int NodeType_function(const char *_tag_,int _type_)
141 {
142  if(_type_&XMLPARSE_TAG_START)
143     current_list=&NodeRules;
144
145  return(0);
146 }
147
148
149 /*++++++++++++++++++++++++++++++++++++++
150   The function that is called when the SetType XSD type is seen
151
152   int SetType_function Returns 0 if no error occured or something else otherwise.
153
154   const char *_tag_ Set to the name of the element tag that triggered this function call.
155
156   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
157
158   const char *k The contents of the 'k' attribute (or NULL if not defined).
159
160   const char *v The contents of the 'v' attribute (or NULL if not defined).
161   ++++++++++++++++++++++++++++++++++++++*/
162
163 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v)
164 {
165  if(_type_&XMLPARSE_TAG_START)
166     AppendTaggingAction(current_rule,k,v,0);
167
168  return(0);
169 }
170
171
172 /*++++++++++++++++++++++++++++++++++++++
173   The function that is called when the OutputType XSD type is seen
174
175   int OutputType_function Returns 0 if no error occured or something else otherwise.
176
177   const char *_tag_ Set to the name of the element tag that triggered this function call.
178
179   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
180
181   const char *k The contents of the 'k' attribute (or NULL if not defined).
182
183   const char *v The contents of the 'v' attribute (or NULL if not defined).
184   ++++++++++++++++++++++++++++++++++++++*/
185
186 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v)
187 {
188  if(_type_&XMLPARSE_TAG_START)
189     AppendTaggingAction(current_rule,k,v,1);
190
191  return(0);
192 }
193
194
195 /*++++++++++++++++++++++++++++++++++++++
196   The function that is called when the RelationType XSD type is seen
197
198   int RelationType_function Returns 0 if no error occured or something else otherwise.
199
200   const char *_tag_ Set to the name of the element tag that triggered this function call.
201
202   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
203   ++++++++++++++++++++++++++++++++++++++*/
204
205 static int RelationType_function(const char *_tag_,int _type_)
206 {
207  if(_type_&XMLPARSE_TAG_START)
208     current_list=&RelationRules;
209
210  return(0);
211 }
212
213
214 /*++++++++++++++++++++++++++++++++++++++
215   The function that is called when the IfType XSD type is seen
216
217   int IfType_function Returns 0 if no error occured or something else otherwise.
218
219   const char *_tag_ Set to the name of the element tag that triggered this function call.
220
221   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
222
223   const char *k The contents of the 'k' attribute (or NULL if not defined).
224
225   const char *v The contents of the 'v' attribute (or NULL if not defined).
226   ++++++++++++++++++++++++++++++++++++++*/
227
228 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v)
229 {
230  if(_type_&XMLPARSE_TAG_START)
231    {
232     current_rule=AppendTaggingRule(current_list,k,v);
233    }
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 }