Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/tagging.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1374 - (show annotations) (download) (as text)
Mon Jun 3 18:52:44 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 27138 byte(s)
Add a new function to convert a TagList into an HTML-like string.

1 /***************************************
2 Load the tagging rules from a file and the functions for handling them.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2010-2013 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <inttypes.h>
27 #include <stdint.h>
28
29 #include "files.h"
30 #include "tagging.h"
31 #include "xmlparse.h"
32 #include "logging.h"
33
34
35 /* Constants */
36
37 #define TAGACTION_IF 1
38 #define TAGACTION_IFNOT 2
39
40 #define TAGACTION_INHERIT 3 /* Not a real action, just a marker */
41
42 #define TAGACTION_SET 4
43 #define TAGACTION_UNSET 5
44 #define TAGACTION_OUTPUT 6
45 #define TAGACTION_LOGERROR 7
46
47
48 /* Local variables */
49
50 static TaggingRuleList NodeRules={NULL,0};
51 static TaggingRuleList WayRules={NULL,0};
52 static TaggingRuleList RelationRules={NULL,0};
53
54 static int current_list_stack_depth=0;
55 static TaggingRuleList **current_list_stack=NULL;
56 static TaggingRuleList *current_list=NULL;
57
58 static int64_t current_id;
59
60 static char *default_logerror_message="ignoring it";
61
62
63 /* Local functions */
64
65 static TaggingRuleList *AppendTaggingRule(TaggingRuleList *rules,const char *k,const char *v,int action);
66 static void AppendTaggingAction(TaggingRuleList *rules,const char *k,const char *v,int action,const char *message);
67 static void DeleteTaggingRuleList(TaggingRuleList *rules);
68
69 static void ApplyRules(TaggingRuleList *rules,TagList *input,TagList *output,const char *match_k,const char *match_v);
70
71
72 /* The XML tag processing function prototypes */
73
74 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
75 //static int RoutinoTaggingType_function(const char *_tag_,int _type_);
76 static int NodeType_function(const char *_tag_,int _type_);
77 static int WayType_function(const char *_tag_,int _type_);
78 static int RelationType_function(const char *_tag_,int _type_);
79 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v);
80 static int IfNotType_function(const char *_tag_,int _type_,const char *k,const char *v);
81 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v);
82 static int UnsetType_function(const char *_tag_,int _type_,const char *k);
83 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v);
84 static int LogErrorType_function(const char *_tag_,int _type_,const char *k,const char *v,const char *message);
85
86
87 /* The XML tag definitions (forward declarations) */
88
89 static xmltag xmlDeclaration_tag;
90 static xmltag RoutinoTaggingType_tag;
91 static xmltag NodeType_tag;
92 static xmltag WayType_tag;
93 static xmltag RelationType_tag;
94 static xmltag IfType_tag;
95 static xmltag IfNotType_tag;
96 static xmltag SetType_tag;
97 static xmltag UnsetType_tag;
98 static xmltag OutputType_tag;
99 static xmltag LogErrorType_tag;
100
101
102 /* The XML tag definition values */
103
104 /*+ The complete set of tags at the top level. +*/
105 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoTaggingType_tag,NULL};
106
107 /*+ The xmlDeclaration type tag. +*/
108 static xmltag xmlDeclaration_tag=
109 {"xml",
110 2, {"version","encoding"},
111 NULL,
112 {NULL}};
113
114 /*+ The RoutinoTaggingType type tag. +*/
115 static xmltag RoutinoTaggingType_tag=
116 {"routino-tagging",
117 0, {NULL},
118 NULL,
119 {&NodeType_tag,&WayType_tag,&RelationType_tag,NULL}};
120
121 /*+ The NodeType type tag. +*/
122 static xmltag NodeType_tag=
123 {"node",
124 0, {NULL},
125 NodeType_function,
126 {&IfType_tag,&IfNotType_tag,NULL}};
127
128 /*+ The WayType type tag. +*/
129 static xmltag WayType_tag=
130 {"way",
131 0, {NULL},
132 WayType_function,
133 {&IfType_tag,&IfNotType_tag,NULL}};
134
135 /*+ The RelationType type tag. +*/
136 static xmltag RelationType_tag=
137 {"relation",
138 0, {NULL},
139 RelationType_function,
140 {&IfType_tag,&IfNotType_tag,NULL}};
141
142 /*+ The IfType type tag. +*/
143 static xmltag IfType_tag=
144 {"if",
145 2, {"k","v"},
146 IfType_function,
147 {&IfType_tag,&IfNotType_tag,&SetType_tag,&UnsetType_tag,&OutputType_tag,&LogErrorType_tag,NULL}};
148
149 /*+ The IfNotType type tag. +*/
150 static xmltag IfNotType_tag=
151 {"ifnot",
152 2, {"k","v"},
153 IfNotType_function,
154 {&IfType_tag,&IfNotType_tag,&SetType_tag,&UnsetType_tag,&OutputType_tag,&LogErrorType_tag,NULL}};
155
156 /*+ The SetType type tag. +*/
157 static xmltag SetType_tag=
158 {"set",
159 2, {"k","v"},
160 SetType_function,
161 {NULL}};
162
163 /*+ The UnsetType type tag. +*/
164 static xmltag UnsetType_tag=
165 {"unset",
166 1, {"k"},
167 UnsetType_function,
168 {NULL}};
169
170 /*+ The OutputType type tag. +*/
171 static xmltag OutputType_tag=
172 {"output",
173 2, {"k","v"},
174 OutputType_function,
175 {NULL}};
176
177 /*+ The LogErrorType type tag. +*/
178 static xmltag LogErrorType_tag=
179 {"logerror",
180 3, {"k","v","message"},
181 LogErrorType_function,
182 {NULL}};
183
184
185 /* The XML tag processing functions */
186
187
188 /*++++++++++++++++++++++++++++++++++++++
189 The function that is called when the XML declaration is seen
190
191 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
192
193 const char *_tag_ Set to the name of the element tag that triggered this function call.
194
195 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
196
197 const char *version The contents of the 'version' attribute (or NULL if not defined).
198
199 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
200 ++++++++++++++++++++++++++++++++++++++*/
201
202 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
203 //{
204 // return(0);
205 //}
206
207
208 /*++++++++++++++++++++++++++++++++++++++
209 The function that is called when the RoutinoTaggingType XSD type is seen
210
211 int RoutinoTaggingType_function Returns 0 if no error occured or something else otherwise.
212
213 const char *_tag_ Set to the name of the element tag that triggered this function call.
214
215 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
216 ++++++++++++++++++++++++++++++++++++++*/
217
218 //static int RoutinoTaggingType_function(const char *_tag_,int _type_)
219 //{
220 // return(0);
221 //}
222
223
224 /*++++++++++++++++++++++++++++++++++++++
225 The function that is called when the NodeType XSD type is seen
226
227 int NodeType_function Returns 0 if no error occured or something else otherwise.
228
229 const char *_tag_ Set to the name of the element tag that triggered this function call.
230
231 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
232 ++++++++++++++++++++++++++++++++++++++*/
233
234 static int NodeType_function(const char *_tag_,int _type_)
235 {
236 if(_type_&XMLPARSE_TAG_START)
237 {
238 current_list_stack_depth=0;
239 current_list=&NodeRules;
240 }
241
242 return(0);
243 }
244
245
246 /*++++++++++++++++++++++++++++++++++++++
247 The function that is called when the WayType XSD type is seen
248
249 int WayType_function Returns 0 if no error occured or something else otherwise.
250
251 const char *_tag_ Set to the name of the element tag that triggered this function call.
252
253 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
254 ++++++++++++++++++++++++++++++++++++++*/
255
256 static int WayType_function(const char *_tag_,int _type_)
257 {
258 if(_type_&XMLPARSE_TAG_START)
259 {
260 current_list_stack_depth=0;
261 current_list=&WayRules;
262 }
263
264 return(0);
265 }
266
267
268 /*++++++++++++++++++++++++++++++++++++++
269 The function that is called when the RelationType XSD type is seen
270
271 int RelationType_function Returns 0 if no error occured or something else otherwise.
272
273 const char *_tag_ Set to the name of the element tag that triggered this function call.
274
275 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
276 ++++++++++++++++++++++++++++++++++++++*/
277
278 static int RelationType_function(const char *_tag_,int _type_)
279 {
280 if(_type_&XMLPARSE_TAG_START)
281 {
282 current_list_stack_depth=0;
283 current_list=&RelationRules;
284 }
285
286 return(0);
287 }
288
289
290 /*++++++++++++++++++++++++++++++++++++++
291 The function that is called when the IfType XSD type is seen
292
293 int IfType_function Returns 0 if no error occured or something else otherwise.
294
295 const char *_tag_ Set to the name of the element tag that triggered this function call.
296
297 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
298
299 const char *k The contents of the 'k' attribute (or NULL if not defined).
300
301 const char *v The contents of the 'v' attribute (or NULL if not defined).
302 ++++++++++++++++++++++++++++++++++++++*/
303
304 static int IfType_function(const char *_tag_,int _type_,const char *k,const char *v)
305 {
306 if(_type_&XMLPARSE_TAG_START)
307 {
308 if(!current_list_stack || (current_list_stack_depth%8)==7)
309 current_list_stack=(TaggingRuleList**)realloc((void*)current_list_stack,(current_list_stack_depth+8)*sizeof(TaggingRuleList*));
310
311 current_list_stack[current_list_stack_depth++]=current_list;
312
313 current_list=AppendTaggingRule(current_list,k,v,TAGACTION_IF);
314 }
315
316 if(_type_&XMLPARSE_TAG_END)
317 current_list=current_list_stack[--current_list_stack_depth];
318
319 return(0);
320 }
321
322
323 /*++++++++++++++++++++++++++++++++++++++
324 The function that is called when the IfNotType XSD type is seen
325
326 int IfNotType_function Returns 0 if no error occured or something else otherwise.
327
328 const char *_tag_ Set to the name of the element tag that triggered this function call.
329
330 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
331
332 const char *k The contents of the 'k' attribute (or NULL if not defined).
333
334 const char *v The contents of the 'v' attribute (or NULL if not defined).
335 ++++++++++++++++++++++++++++++++++++++*/
336
337 static int IfNotType_function(const char *_tag_,int _type_,const char *k,const char *v)
338 {
339 if(_type_&XMLPARSE_TAG_START)
340 {
341 if(!current_list_stack || (current_list_stack_depth%8)==7)
342 current_list_stack=(TaggingRuleList**)realloc((void*)current_list_stack,(current_list_stack_depth+8)*sizeof(TaggingRuleList*));
343
344 current_list_stack[current_list_stack_depth++]=current_list;
345
346 current_list=AppendTaggingRule(current_list,k,v,TAGACTION_IFNOT);
347 }
348
349 if(_type_&XMLPARSE_TAG_END)
350 current_list=current_list_stack[--current_list_stack_depth];
351
352 return(0);
353 }
354
355
356 /*++++++++++++++++++++++++++++++++++++++
357 The function that is called when the SetType XSD type is seen
358
359 int SetType_function Returns 0 if no error occured or something else otherwise.
360
361 const char *_tag_ Set to the name of the element tag that triggered this function call.
362
363 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
364
365 const char *k The contents of the 'k' attribute (or NULL if not defined).
366
367 const char *v The contents of the 'v' attribute (or NULL if not defined).
368 ++++++++++++++++++++++++++++++++++++++*/
369
370 static int SetType_function(const char *_tag_,int _type_,const char *k,const char *v)
371 {
372 if(_type_&XMLPARSE_TAG_START)
373 AppendTaggingAction(current_list,k,v,TAGACTION_SET,NULL);
374
375 return(0);
376 }
377
378
379 /*++++++++++++++++++++++++++++++++++++++
380 The function that is called when the UnsetType XSD type is seen
381
382 int UnsetType_function Returns 0 if no error occured or something else otherwise.
383
384 const char *_tag_ Set to the name of the element tag that triggered this function call.
385
386 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
387
388 const char *k The contents of the 'k' attribute (or NULL if not defined).
389 ++++++++++++++++++++++++++++++++++++++*/
390
391 static int UnsetType_function(const char *_tag_,int _type_,const char *k)
392 {
393 if(_type_&XMLPARSE_TAG_START)
394 AppendTaggingAction(current_list,k,NULL,TAGACTION_UNSET,NULL);
395
396 return(0);
397 }
398
399
400 /*++++++++++++++++++++++++++++++++++++++
401 The function that is called when the OutputType XSD type is seen
402
403 int OutputType_function Returns 0 if no error occured or something else otherwise.
404
405 const char *_tag_ Set to the name of the element tag that triggered this function call.
406
407 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
408
409 const char *k The contents of the 'k' attribute (or NULL if not defined).
410
411 const char *v The contents of the 'v' attribute (or NULL if not defined).
412 ++++++++++++++++++++++++++++++++++++++*/
413
414 static int OutputType_function(const char *_tag_,int _type_,const char *k,const char *v)
415 {
416 if(_type_&XMLPARSE_TAG_START)
417 AppendTaggingAction(current_list,k,v,TAGACTION_OUTPUT,NULL);
418
419 return(0);
420 }
421
422
423 /*++++++++++++++++++++++++++++++++++++++
424 The function that is called when the LogErrorType XSD type is seen
425
426 int LogErrorType_function Returns 0 if no error occured or something else otherwise.
427
428 const char *_tag_ Set to the name of the element tag that triggered this function call.
429
430 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
431
432 const char *k The contents of the 'k' attribute (or NULL if not defined).
433
434 const char *v The contents of the 'v' attribute (or NULL if not defined).
435
436 const char *message The contents of the 'message' attribute (or NULL if not defined).
437 ++++++++++++++++++++++++++++++++++++++*/
438
439 static int LogErrorType_function(const char *_tag_,int _type_,const char *k,const char *v,const char *message)
440 {
441 if(_type_&XMLPARSE_TAG_START)
442 AppendTaggingAction(current_list,k,v,TAGACTION_LOGERROR,message);
443
444 return(0);
445 }
446
447
448 /*++++++++++++++++++++++++++++++++++++++
449 The XML tagging rules parser.
450
451 int ParseXMLTaggingRules Returns 0 if OK or something else in case of an error.
452
453 const char *filename The name of the file to read.
454 ++++++++++++++++++++++++++++++++++++++*/
455
456 int ParseXMLTaggingRules(const char *filename)
457 {
458 int fd;
459 int retval;
460
461 if(!ExistsFile(filename))
462 {
463 fprintf(stderr,"Error: Specified tagging rules file '%s' does not exist.\n",filename);
464 return(1);
465 }
466
467 fd=ReOpenFile(filename);
468
469 retval=ParseXML(fd,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME);
470
471 CloseFile(fd);
472
473 if(current_list_stack)
474 free(current_list_stack);
475
476 if(retval)
477 return(1);
478
479 return(0);
480 }
481
482
483 /*++++++++++++++++++++++++++++++++++++++
484 Delete the tagging rules loaded from the XML file.
485 ++++++++++++++++++++++++++++++++++++++*/
486
487 void DeleteXMLTaggingRules(void)
488 {
489 DeleteTaggingRuleList(&NodeRules);
490 DeleteTaggingRuleList(&WayRules);
491 DeleteTaggingRuleList(&RelationRules);
492 }
493
494
495 /*++++++++++++++++++++++++++++++++++++++
496 Append a tagging rule to the list of rules.
497
498 TaggingRuleList *AppendTaggingRule Returns the new TaggingRuleList inside the new TaggingRule.
499
500 TaggingRuleList *rules The list of rules to add to.
501
502 const char *k The tag key.
503
504 const char *v The tag value.
505
506 int action Set to the type of action.
507 ++++++++++++++++++++++++++++++++++++++*/
508
509 TaggingRuleList *AppendTaggingRule(TaggingRuleList *rules,const char *k,const char *v,int action)
510 {
511 if((rules->nrules%16)==0)
512 rules->rules=(TaggingRule*)realloc((void*)rules->rules,(rules->nrules+16)*sizeof(TaggingRule));
513
514 rules->nrules++;
515
516 rules->rules[rules->nrules-1].action=action;
517
518 if(k)
519 rules->rules[rules->nrules-1].k=strcpy(malloc(strlen(k)+1),k);
520 else
521 rules->rules[rules->nrules-1].k=NULL;
522
523 if(v)
524 rules->rules[rules->nrules-1].v=strcpy(malloc(strlen(v)+1),v);
525 else
526 rules->rules[rules->nrules-1].v=NULL;
527
528 rules->rules[rules->nrules-1].message=NULL;
529
530 rules->rules[rules->nrules-1].rulelist=(TaggingRuleList*)calloc(sizeof(TaggingRuleList),1);
531
532 return(rules->rules[rules->nrules-1].rulelist);
533 }
534
535
536 /*++++++++++++++++++++++++++++++++++++++
537 Append a tagging action to the list of rules.
538
539 TaggingRuleList *rules The list of rules to add to.
540
541 const char *k The tag key.
542
543 const char *v The tag value.
544
545 int action Set to the type of action.
546
547 const char *message The message to use for the logerror action.
548 ++++++++++++++++++++++++++++++++++++++*/
549
550 static void AppendTaggingAction(TaggingRuleList *rules,const char *k,const char *v,int action,const char *message)
551 {
552 if((rules->nrules%16)==0)
553 rules->rules=(TaggingRule*)realloc((void*)rules->rules,(rules->nrules+16)*sizeof(TaggingRule));
554
555 rules->nrules++;
556
557 rules->rules[rules->nrules-1].action=action;
558
559 if(k)
560 rules->rules[rules->nrules-1].k=strcpy(malloc(strlen(k)+1),k);
561 else
562 rules->rules[rules->nrules-1].k=NULL;
563
564 if(v)
565 rules->rules[rules->nrules-1].v=strcpy(malloc(strlen(v)+1),v);
566 else
567 rules->rules[rules->nrules-1].v=NULL;
568
569 if(message)
570 rules->rules[rules->nrules-1].message=strcpy(malloc(strlen(message)+1),message);
571 else
572 rules->rules[rules->nrules-1].message=default_logerror_message;
573
574 rules->rules[rules->nrules-1].rulelist=NULL;
575 }
576
577
578 /*++++++++++++++++++++++++++++++++++++++
579 Delete a tagging rule.
580
581 TaggingRuleList *rules The list of rules to be deleted.
582 ++++++++++++++++++++++++++++++++++++++*/
583
584 void DeleteTaggingRuleList(TaggingRuleList *rules)
585 {
586 int i;
587
588 for(i=0;i<rules->nrules;i++)
589 {
590 if(rules->rules[i].k)
591 free(rules->rules[i].k);
592 if(rules->rules[i].v)
593 free(rules->rules[i].v);
594 if(rules->rules[i].message && rules->rules[i].message!=default_logerror_message)
595 free(rules->rules[i].message);
596
597 if(rules->rules[i].rulelist)
598 {
599 DeleteTaggingRuleList(rules->rules[i].rulelist);
600 free(rules->rules[i].rulelist);
601 }
602 }
603
604 if(rules->rules)
605 free(rules->rules);
606 }
607
608
609 /*++++++++++++++++++++++++++++++++++++++
610 Create a new TagList structure.
611
612 TagList *NewTagList Returns the new allocated TagList.
613 ++++++++++++++++++++++++++++++++++++++*/
614
615 TagList *NewTagList(void)
616 {
617 return((TagList*)calloc(sizeof(TagList),1));
618 }
619
620
621 /*++++++++++++++++++++++++++++++++++++++
622 Delete a tag list and the contents.
623
624 TagList *tags The list of tags to delete.
625 ++++++++++++++++++++++++++++++++++++++*/
626
627 void DeleteTagList(TagList *tags)
628 {
629 int i;
630
631 for(i=0;i<tags->ntags;i++)
632 {
633 if(tags->k[i]) free(tags->k[i]);
634 if(tags->v[i]) free(tags->v[i]);
635 }
636
637 if(tags->k) free(tags->k);
638 if(tags->v) free(tags->v);
639
640 free(tags);
641 }
642
643
644 /*++++++++++++++++++++++++++++++++++++++
645 Append a tag to the list of tags.
646
647 TagList *tags The list of tags to add to.
648
649 const char *k The tag key.
650
651 const char *v The tag value.
652 ++++++++++++++++++++++++++++++++++++++*/
653
654 void AppendTag(TagList *tags,const char *k,const char *v)
655 {
656 if((tags->ntags%8)==0)
657 {
658 int i;
659
660 tags->k=(char**)realloc((void*)tags->k,(tags->ntags+8)*sizeof(char*));
661 tags->v=(char**)realloc((void*)tags->v,(tags->ntags+8)*sizeof(char*));
662
663 for(i=tags->ntags;i<(tags->ntags+8);i++)
664 tags->k[i]=tags->v[i]=NULL;
665 }
666
667 tags->k[tags->ntags]=strcpy(realloc(tags->k[tags->ntags],strlen(k)+1),k);
668 tags->v[tags->ntags]=strcpy(realloc(tags->v[tags->ntags],strlen(v)+1),v);
669
670 tags->ntags++;
671 }
672
673
674 /*++++++++++++++++++++++++++++++++++++++
675 Modify an existing tag or append a new tag to the list of tags.
676
677 TagList *tags The list of tags to modify.
678
679 const char *k The tag key.
680
681 const char *v The tag value.
682 ++++++++++++++++++++++++++++++++++++++*/
683
684 void ModifyTag(TagList *tags,const char *k,const char *v)
685 {
686 int i;
687
688 for(i=0;i<tags->ntags;i++)
689 if(!strcmp(tags->k[i],k))
690 {
691 tags->v[i]=strcpy(realloc(tags->v[i],strlen(v)+1),v);
692 return;
693 }
694
695 AppendTag(tags,k,v);
696 }
697
698
699 /*++++++++++++++++++++++++++++++++++++++
700 Delete an existing tag from the list of tags.
701
702 TagList *tags The list of tags to modify.
703
704 const char *k The tag key.
705 ++++++++++++++++++++++++++++++++++++++*/
706
707 void DeleteTag(TagList *tags,const char *k)
708 {
709 int i,j;
710
711 for(i=0;i<tags->ntags;i++)
712 if(!strcmp(tags->k[i],k))
713 {
714 if(tags->k[i]) free(tags->k[i]);
715 if(tags->v[i]) free(tags->v[i]);
716
717 for(j=i+1;j<tags->ntags;j++)
718 {
719 tags->k[j-1]=tags->k[j];
720 tags->v[j-1]=tags->v[j];
721 }
722
723 tags->ntags--;
724
725 tags->k[tags->ntags]=NULL;
726 tags->v[tags->ntags]=NULL;
727
728 return;
729 }
730 }
731
732
733 /*++++++++++++++++++++++++++++++++++++++
734 Create a string containing all of the tags formatted as if HTML.
735
736 char *StringifyTag Returns a static pointer to the created string.
737
738 TagList *tags The list of tags to convert.
739 ++++++++++++++++++++++++++++++++++++++*/
740
741 char *StringifyTag(TagList *tags)
742 {
743 static char *string=NULL;
744 int i,length=0,used=0;
745
746 for(i=0;i<tags->ntags;i++)
747 {
748 length+=strlen(tags->k[i]);
749 length+=strlen(tags->v[i]);
750
751 length+=16;
752 }
753
754 string=realloc((char*)string,length);
755
756 for(i=0;i<tags->ntags;i++)
757 used+=sprintf(string+used,"<tag k='%s' v='%s'>",tags->k[i],tags->v[i]);
758
759 return(string);
760 }
761
762
763 /*++++++++++++++++++++++++++++++++++++++
764 Apply a set of tagging rules to a set of node tags.
765
766 TagList *ApplyTaggingRules Returns the list of output tags after modification.
767
768 TagList *tags The tags to be modified.
769
770 int64_t id The ID of the node.
771 ++++++++++++++++++++++++++++++++++++++*/
772
773 TagList *ApplyNodeTaggingRules(TagList *tags,int64_t id)
774 {
775 TagList *result=NewTagList();
776
777 current_id=id;
778 current_list=&NodeRules;
779
780 ApplyRules(current_list,tags,result,NULL,NULL);
781
782 return(result);
783 }
784
785
786 /*++++++++++++++++++++++++++++++++++++++
787 Apply a set of tagging rules to a set of way tags.
788
789 TagList *ApplyTaggingRules Returns the list of output tags after modification.
790
791 TagList *tags The tags to be modified.
792
793 int64_t id The ID of the way.
794 ++++++++++++++++++++++++++++++++++++++*/
795
796 TagList *ApplyWayTaggingRules(TagList *tags,int64_t id)
797 {
798 TagList *result=NewTagList();
799
800 current_id=id;
801 current_list=&WayRules;
802
803 ApplyRules(current_list,tags,result,NULL,NULL);
804
805 return(result);
806 }
807
808
809 /*++++++++++++++++++++++++++++++++++++++
810 Apply a set of tagging rules to a set of relation tags.
811
812 TagList *ApplyTaggingRules Returns the list of output tags after modification.
813
814 TagList *tags The tags to be modified.
815
816 int64_t id The ID of the relation.
817 ++++++++++++++++++++++++++++++++++++++*/
818
819 TagList *ApplyRelationTaggingRules(TagList *tags,int64_t id)
820 {
821 TagList *result=NewTagList();
822
823 current_id=id;
824 current_list=&RelationRules;
825
826 ApplyRules(current_list,tags,result,NULL,NULL);
827
828 return(result);
829 }
830
831
832 /*++++++++++++++++++++++++++++++++++++++
833 Apply a set of rules to a matching tag.
834
835 TaggingRuleList *rules The rules that are to be matched.
836
837 TagList *input The input tags.
838
839 TagList *output The output tags.
840
841 const char *match_k The key matched at the higher level rule.
842
843 const char *match_v The value matched at the higher level rule.
844 ++++++++++++++++++++++++++++++++++++++*/
845
846 static void ApplyRules(TaggingRuleList *rules,TagList *input,TagList *output,const char *match_k,const char *match_v)
847 {
848 int i,j;
849 char *match_k_copy=NULL,*match_v_copy=NULL;
850
851 if(match_k)
852 match_k_copy=strcpy(malloc(strlen(match_k)+1),match_k);
853
854 if(match_v)
855 match_v_copy=strcpy(malloc(strlen(match_v)+1),match_v);
856
857 for(i=0;i<rules->nrules;i++)
858 {
859 const char *k,*v;
860
861 k=rules->rules[i].k;
862
863 if(!k && rules->rules[i].action >= TAGACTION_INHERIT)
864 k=match_k_copy;
865
866 v=rules->rules[i].v;
867
868 if(!v && rules->rules[i].action >= TAGACTION_INHERIT)
869 v=match_v_copy;
870
871 switch(rules->rules[i].action)
872 {
873 case TAGACTION_IF:
874 if(k && v)
875 {
876 for(j=0;j<input->ntags;j++)
877 if(!strcmp(input->k[j],k) && !strcmp(input->v[j],v))
878 ApplyRules(rules->rules[i].rulelist,input,output,input->k[j],input->v[j]);
879 }
880 else if(k && !v)
881 {
882 for(j=0;j<input->ntags;j++)
883 if(!strcmp(input->k[j],k))
884 ApplyRules(rules->rules[i].rulelist,input,output,input->k[j],input->v[j]);
885 }
886 else if(!k && v)
887 {
888 for(j=0;j<input->ntags;j++)
889 if(!strcmp(input->v[j],v))
890 ApplyRules(rules->rules[i].rulelist,input,output,input->k[j],input->v[j]);
891 }
892 else /* if(!k && !v) */
893 {
894 for(j=0;j<input->ntags;j++)
895 ApplyRules(rules->rules[i].rulelist,input,output,input->k[j],input->v[j]);
896 }
897 break;
898
899 case TAGACTION_IFNOT:
900 if(k && v)
901 {
902 for(j=0;j<input->ntags;j++)
903 if(!strcmp(input->k[j],k) && !strcmp(input->v[j],v))
904 break;
905
906 if(j!=input->ntags)
907 break;
908 }
909 else if(k && !v)
910 {
911 for(j=0;j<input->ntags;j++)
912 if(!strcmp(input->k[j],k))
913 break;
914
915 if(j!=input->ntags)
916 break;
917 }
918 else if(!k && v)
919 {
920 for(j=0;j<input->ntags;j++)
921 if(!strcmp(input->v[j],v))
922 break;
923
924 if(j!=input->ntags)
925 break;
926 }
927 else /* if(!k && !v) */
928 {
929 break;
930 }
931
932 ApplyRules(rules->rules[i].rulelist,input,output,k,v);
933 break;
934
935 case TAGACTION_SET:
936 ModifyTag(input,k,v);
937 break;
938
939 case TAGACTION_UNSET:
940 DeleteTag(input,k);
941 break;
942
943 case TAGACTION_OUTPUT:
944 ModifyTag(output,k,v);
945 break;
946
947 case TAGACTION_LOGERROR:
948 if(rules->rules[i].k && !rules->rules[i].v)
949 for(j=0;j<input->ntags;j++)
950 if(!strcmp(input->k[j],rules->rules[i].k))
951 {
952 v=input->v[j];
953 break;
954 }
955
956 if(current_list==&NodeRules)
957 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (in tagging rules); %s.\n",logerror_node(current_id),k,v,rules->rules[i].message);
958 if(current_list==&WayRules)
959 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (in tagging rules); %s.\n",logerror_way(current_id),k,v,rules->rules[i].message);
960 if(current_list==&RelationRules)
961 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (in tagging rules); %s.\n",logerror_relation(current_id),k,v,rules->rules[i].message);
962 }
963 }
964
965 if(match_k_copy) free(match_k_copy);
966 if(match_v_copy) free(match_v_copy);
967 }

Properties

Name Value
cvs:description Functions for reading the tag transformation rules and applying them.