1 /***************************************
2 $Header: /home/amb/routino/src/RCS/tagging.c,v 1.5 2010/09/17 17:40:41 amb Exp $
4 Load the tagging rules from a file and the functions for handling them.
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2010 Andrew M. Bishop
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.
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.
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 ***************************************/
34 /* Global variables */
36 TaggingRuleList NodeRules={NULL,0};
37 TaggingRuleList WayRules={NULL,0};
38 TaggingRuleList RelationRules={NULL,0};
43 TaggingRuleList *current_list=NULL;
44 TaggingRule *current_rule=NULL;
49 static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output);
52 /* The XML tag processing function prototypes */
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);
64 /* The XML tag definitions */
66 /*+ The SetType type tag. +*/
67 static xmltag SetType_tag=
73 /*+ The OutputType type tag. +*/
74 static xmltag OutputType_tag=
80 /*+ The IfType type tag. +*/
81 static xmltag IfType_tag=
85 {&SetType_tag,&OutputType_tag,NULL}};
87 /*+ The RelationType type tag. +*/
88 static xmltag RelationType_tag=
91 RelationType_function,
94 /*+ The NodeType type tag. +*/
95 static xmltag NodeType_tag=
101 /*+ The WayType type tag. +*/
102 static xmltag WayType_tag=
108 /*+ The RoutinoTaggingType type tag. +*/
109 static xmltag RoutinoTaggingType_tag=
113 {&NodeType_tag,&WayType_tag,&RelationType_tag,NULL}};
115 /*+ The xmlDeclaration type tag. +*/
116 static xmltag xmlDeclaration_tag=
118 2, {"version","encoding"},
123 /*+ The complete set of tags at the top level. +*/
124 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoTaggingType_tag,NULL};
127 /* The XML tag processing functions */
130 /*++++++++++++++++++++++++++++++++++++++
131 The function that is called when the SetType XSD type is seen
133 int SetType_function Returns 0 if no error occured or something else otherwise.
135 const char *_tag_ Set to the name of the element tag that triggered this function call.
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.
139 const char *k The contents of the 'k' attribute (or NULL if not defined).
141 const char *v The contents of the 'v' attribute (or NULL if not defined).
142 ++++++++++++++++++++++++++++++++++++++*/
144 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v)
146 if(_type_&XMLPARSE_TAG_START)
147 AppendTaggingAction(current_rule,k,v,0);
153 /*++++++++++++++++++++++++++++++++++++++
154 The function that is called when the OutputType XSD type is seen
156 int OutputType_function Returns 0 if no error occured or something else otherwise.
158 const char *_tag_ Set to the name of the element tag that triggered this function call.
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.
162 const char *k The contents of the 'k' attribute (or NULL if not defined).
164 const char *v The contents of the 'v' attribute (or NULL if not defined).
165 ++++++++++++++++++++++++++++++++++++++*/
167 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v)
169 if(_type_&XMLPARSE_TAG_START)
170 AppendTaggingAction(current_rule,k,v,1);
176 /*++++++++++++++++++++++++++++++++++++++
177 The function that is called when the IfType XSD type is seen
179 int IfType_function Returns 0 if no error occured or something else otherwise.
181 const char *_tag_ Set to the name of the element tag that triggered this function call.
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.
185 const char *k The contents of the 'k' attribute (or NULL if not defined).
187 const char *v The contents of the 'v' attribute (or NULL if not defined).
188 ++++++++++++++++++++++++++++++++++++++*/
190 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v)
192 if(_type_&XMLPARSE_TAG_START)
194 current_rule=AppendTaggingRule(current_list,k,v);
201 /*++++++++++++++++++++++++++++++++++++++
202 The function that is called when the RelationType XSD type is seen
204 int RelationType_function Returns 0 if no error occured or something else otherwise.
206 const char *_tag_ Set to the name of the element tag that triggered this function call.
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 ++++++++++++++++++++++++++++++++++++++*/
211 static int RelationType_function(const char *_tag_,int _type_)
213 if(_type_&XMLPARSE_TAG_START)
214 current_list=&RelationRules;
220 /*++++++++++++++++++++++++++++++++++++++
221 The function that is called when the NodeType XSD type is seen
223 int NodeType_function Returns 0 if no error occured or something else otherwise.
225 const char *_tag_ Set to the name of the element tag that triggered this function call.
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 ++++++++++++++++++++++++++++++++++++++*/
230 static int NodeType_function(const char *_tag_,int _type_)
232 if(_type_&XMLPARSE_TAG_START)
233 current_list=&NodeRules;
239 /*++++++++++++++++++++++++++++++++++++++
240 The function that is called when the WayType XSD type is seen
242 int WayType_function Returns 0 if no error occured or something else otherwise.
244 const char *_tag_ Set to the name of the element tag that triggered this function call.
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 ++++++++++++++++++++++++++++++++++++++*/
249 static int WayType_function(const char *_tag_,int _type_)
251 if(_type_&XMLPARSE_TAG_START)
252 current_list=&WayRules;
258 /*++++++++++++++++++++++++++++++++++++++
259 The function that is called when the RoutinoTaggingType XSD type is seen
261 int RoutinoTaggingType_function Returns 0 if no error occured or something else otherwise.
263 const char *_tag_ Set to the name of the element tag that triggered this function call.
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 ++++++++++++++++++++++++++++++++++++++*/
268 //static int RoutinoTaggingType_function(const char *_tag_,int _type_)
274 /*++++++++++++++++++++++++++++++++++++++
275 The function that is called when the XML declaration is seen
277 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
279 const char *_tag_ Set to the name of the element tag that triggered this function call.
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.
283 const char *version The contents of the 'version' attribute (or NULL if not defined).
285 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
286 ++++++++++++++++++++++++++++++++++++++*/
288 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
294 /*++++++++++++++++++++++++++++++++++++++
295 The XML tagging rules parser.
297 int ParseXMLTaggingRules Returns 0 if OK or something else in case of an error.
299 const char *filename The name of the file to read.
300 ++++++++++++++++++++++++++++++++++++++*/
302 int ParseXMLTaggingRules(const char *filename)
306 if(!ExistsFile(filename))
308 fprintf(stderr,"Error: Specified tagging rules file '%s' does not exist.\n",filename);
312 FILE *file=fopen(filename,"r");
316 fprintf(stderr,"Error: Cannot open tagging rules file '%s' for reading.\n",filename);
320 retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME);
331 /*++++++++++++++++++++++++++++++++++++++
332 Append a tagging rule to the list of rules.
334 TaggingRule *AppendTaggingRule Returns the latest rule (the just added one).
336 TaggingRuleList *rules The list of rules to add to.
338 const char *k The tag key.
340 const char *v The tag value.
341 ++++++++++++++++++++++++++++++++++++++*/
343 TaggingRule *AppendTaggingRule(TaggingRuleList *rules,const char *k,const char *v)
345 if((rules->nrules%16)==0)
346 rules->rules=(TaggingRule*)realloc((void*)rules->rules,(rules->nrules+16)*sizeof(TaggingRule));
351 rules->rules[rules->nrules-1].k=strcpy(malloc(strlen(k)+1),k);
353 rules->rules[rules->nrules-1].k=NULL;
356 rules->rules[rules->nrules-1].v=strcpy(malloc(strlen(v)+1),v);
358 rules->rules[rules->nrules-1].v=NULL;
360 rules->rules[rules->nrules-1].nactions=0;
361 rules->rules[rules->nrules-1].actions=NULL;
363 return(&rules->rules[rules->nrules-1]);
367 /*++++++++++++++++++++++++++++++++++++++
368 Append a tagging action to a tagging rule.
370 TaggingRule *rule The rule to add the action to.
372 const char *k The tag key.
374 const char *v The tag value.
376 int output Set to 1 if this is an output rule.
377 ++++++++++++++++++++++++++++++++++++++*/
379 void AppendTaggingAction(TaggingRule *rule,const char *k,const char *v,int output)
381 if((rule->nactions%16)==0)
382 rule->actions=(TaggingAction*)realloc((void*)rule->actions,(rule->nactions+16)*sizeof(TaggingAction));
386 rule->actions[rule->nactions-1].output=output;
389 rule->actions[rule->nactions-1].k=strcpy(malloc(strlen(k)+1),k);
391 rule->actions[rule->nactions-1].k=NULL;
394 rule->actions[rule->nactions-1].v=strcpy(malloc(strlen(v)+1),v);
396 rule->actions[rule->nactions-1].v=NULL;
400 /*++++++++++++++++++++++++++++++++++++++
401 Create a new TagList structure.
403 TagList *NewTagList Returns the new allocated TagList.
404 ++++++++++++++++++++++++++++++++++++++*/
406 TagList *NewTagList(void)
408 return((TagList*)calloc(sizeof(TagList),1));
412 /*++++++++++++++++++++++++++++++++++++++
413 Append a tag to the list of tags.
415 TagList *tags The list of tags to add to.
417 const char *k The tag key.
419 const char *v The tag value.
420 ++++++++++++++++++++++++++++++++++++++*/
422 void AppendTag(TagList *tags,const char *k,const char *v)
424 if((tags->ntags%16)==0)
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*));
431 for(i=tags->ntags;i<(tags->ntags+16);i++)
432 tags->k[i]=tags->v[i]=NULL;
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);
442 /*++++++++++++++++++++++++++++++++++++++
443 Modify an existing tag or append a new tag to the list of tags.
445 TagList *tags The list of tags to modify.
447 const char *k The tag key.
449 const char *v The tag value.
450 ++++++++++++++++++++++++++++++++++++++*/
452 void ModifyTag(TagList *tags,const char *k,const char *v)
456 for(i=0;i<tags->ntags;i++)
457 if(!strcmp(tags->k[i],k))
459 tags->v[i]=strcpy(realloc(tags->v[i],strlen(v)+1),v);
467 /*++++++++++++++++++++++++++++++++++++++
468 Delete a tag list and the contents.
470 TagList *tags The list of tags to delete.
471 ++++++++++++++++++++++++++++++++++++++*/
473 void DeleteTagList(TagList *tags)
477 for(i=0;i<tags->ntags;i++)
479 if(tags->k[i]) free(tags->k[i]);
480 if(tags->v[i]) free(tags->v[i]);
493 /*++++++++++++++++++++++++++++++++++++++
494 Apply a set of tagging rules to a set of tags.
496 TagList *ApplyTaggingRules Returns the list of output tags after modification.
498 TaggingRuleList *rules The tagging rules to apply.
500 TagList *tags The tags to be modified.
501 ++++++++++++++++++++++++++++++++++++++*/
503 TagList *ApplyTaggingRules(TaggingRuleList *rules,TagList *tags)
505 TagList *result=NewTagList();
508 for(i=0;i<rules->nrules;i++)
510 if(rules->rules[i].k && rules->rules[i].v)
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);
516 else if(rules->rules[i].k && !rules->rules[i].v)
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);
522 else if(!rules->rules[i].k && rules->rules[i].v)
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);
528 else /* if(!rules->rules[i].k && !rules->rules[i].v) */
530 for(j=0;j<tags->ntags;j++)
531 apply_actions(&rules->rules[i],j,tags,result);
539 /*++++++++++++++++++++++++++++++++++++++
540 Apply a set of actions to a matching tag.
542 TaggingRule *rule The rule that matched (containing the actions).
544 int match The matching tag number.
546 TagList *input The input tags.
548 TagList *output The output tags.
549 ++++++++++++++++++++++++++++++++++++++*/
551 static void apply_actions(TaggingRule *rule,int match,TagList *input,TagList *output)
555 for(i=0;i<rule->nactions;i++)
559 if(rule->actions[i].k)
560 k=rule->actions[i].k;
564 if(rule->actions[i].v)
565 v=rule->actions[i].v;
569 if(rule->actions[i].output)
570 ModifyTag(output,k,v);
572 ModifyTag(input,k,v);