Routino SVN Repository Browser

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

ViewVC logotype

Annotation of /trunk/src/osmparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 812 - (hide annotations) (download) (as text)
Thu Jul 21 18:44:52 2011 UTC (13 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 36768 byte(s)
Add logging of parsing and processing errors.

1 amb 2 /***************************************
2     OSM XML file parser (either JOSM or planet)
3 amb 151
4     Part of the Routino routing software.
5 amb 2 ******************/ /******************
6 amb 643 This file Copyright 2008-2011 Andrew M. Bishop
7 amb 2
8 amb 151 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 amb 2 ***************************************/
21    
22    
23 amb 776 #include <assert.h>
24 amb 2 #include <stdio.h>
25     #include <stdlib.h>
26     #include <string.h>
27     #include <ctype.h>
28    
29 amb 199 #include "typesx.h"
30     #include "functionsx.h"
31 amb 498
32 amb 109 #include "nodesx.h"
33     #include "segmentsx.h"
34     #include "waysx.h"
35 amb 498 #include "relationsx.h"
36    
37 amb 394 #include "xmlparse.h"
38     #include "tagging.h"
39 amb 2
40 amb 519 #include "logging.h"
41 amb 26
42 amb 519
43 amb 394 /* Macros */
44 amb 2
45 amb 680 /*+ Checks if a value in the XML is one of the allowed values for true. +*/
46 amb 812 #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1"))
47 amb 297
48 amb 812 /*+ Checks if a value in the XML is one of the allowed values for false. +*/
49     #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0"))
50 amb 298
51 amb 812
52 amb 394 /* Local variables */
53    
54 amb 790 static index_t nnodes=0;
55     static index_t nways=0;
56     static index_t nrelations=0;
57    
58 amb 401 static TagList *current_tags=NULL;
59 amb 394
60     static node_t *way_nodes=NULL;
61     static int way_nnodes=0;
62    
63 amb 498 static node_t *relation_nodes=NULL;
64     static int relation_nnodes=0;
65     static way_t *relation_ways=NULL;
66     static int relation_nways=0;
67     static relation_t *relation_relations=NULL;
68     static int relation_nrelations=0;
69 amb 755 static way_t relation_from=NO_WAY_ID;
70     static way_t relation_to=NO_WAY_ID;
71     static node_t relation_via=NO_NODE_ID;
72 amb 394
73 amb 498 static NodesX *nodes;
74     static SegmentsX *segments;
75     static WaysX *ways;
76     static RelationsX *relations;
77 amb 394
78 amb 498
79 amb 228 /* Local functions */
80    
81 amb 469 static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude);
82 amb 394 static void process_way_tags(TagList *tags,way_t id);
83 amb 498 static void process_relation_tags(TagList *tags,relation_t id);
84 amb 2
85 amb 812 static double parse_speed(way_t id,const char *k,const char *v);
86     static double parse_weight(way_t id,const char *k,const char *v);
87     static double parse_length(way_t id,const char *k,const char *v);
88 amb 2
89 amb 812
90 amb 394 /* The XML tag processing function prototypes */
91 amb 2
92 amb 394 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
93     //static int osmType_function(const char *_tag_,int _type_);
94     static int relationType_function(const char *_tag_,int _type_,const char *id);
95     static int wayType_function(const char *_tag_,int _type_,const char *id);
96 amb 498 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
97 amb 394 static int ndType_function(const char *_tag_,int _type_,const char *ref);
98     static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon);
99     static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
100 amb 399 //static int boundType_function(const char *_tag_,int _type_);
101 amb 394 //static int boundsType_function(const char *_tag_,int _type_);
102 amb 2
103 amb 26
104 amb 394 /* The XML tag definitions */
105 amb 26
106 amb 394 /*+ The boundsType type tag. +*/
107     static xmltag boundsType_tag=
108     {"bounds",
109     0, {NULL},
110     NULL,
111     {NULL}};
112 amb 26
113 amb 399 /*+ The boundType type tag. +*/
114     static xmltag boundType_tag=
115     {"bound",
116     0, {NULL},
117     NULL,
118     {NULL}};
119    
120 amb 394 /*+ The tagType type tag. +*/
121     static xmltag tagType_tag=
122     {"tag",
123     2, {"k","v"},
124     tagType_function,
125     {NULL}};
126 amb 75
127 amb 394 /*+ The nodeType type tag. +*/
128     static xmltag nodeType_tag=
129     {"node",
130     3, {"id","lat","lon"},
131     nodeType_function,
132     {&tagType_tag,NULL}};
133 amb 2
134 amb 394 /*+ The ndType type tag. +*/
135     static xmltag ndType_tag=
136     {"nd",
137     1, {"ref"},
138     ndType_function,
139     {NULL}};
140 amb 2
141 amb 394 /*+ The memberType type tag. +*/
142     static xmltag memberType_tag=
143     {"member",
144     3, {"type","ref","role"},
145 amb 498 memberType_function,
146 amb 394 {NULL}};
147 amb 227
148 amb 394 /*+ The wayType type tag. +*/
149     static xmltag wayType_tag=
150     {"way",
151     1, {"id"},
152     wayType_function,
153     {&ndType_tag,&tagType_tag,NULL}};
154 amb 2
155 amb 394 /*+ The relationType type tag. +*/
156     static xmltag relationType_tag=
157     {"relation",
158     1, {"id"},
159     relationType_function,
160     {&memberType_tag,&tagType_tag,NULL}};
161 amb 2
162 amb 394 /*+ The osmType type tag. +*/
163     static xmltag osmType_tag=
164     {"osm",
165     0, {NULL},
166     NULL,
167 amb 399 {&boundsType_tag,&boundType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
168 amb 2
169 amb 394 /*+ The xmlDeclaration type tag. +*/
170     static xmltag xmlDeclaration_tag=
171     {"xml",
172     2, {"version","encoding"},
173     NULL,
174     {NULL}};
175 amb 2
176    
177 amb 394 /*+ The complete set of tags at the top level. +*/
178     static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
179 amb 2
180    
181 amb 394 /* The XML tag processing functions */
182 amb 2
183 amb 159
184 amb 394 /*++++++++++++++++++++++++++++++++++++++
185     The function that is called when the boundsType XSD type is seen
186 amb 2
187 amb 394 int boundsType_function Returns 0 if no error occured or something else otherwise.
188 amb 2
189 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
190 amb 203
191 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
192     ++++++++++++++++++++++++++++++++++++++*/
193 amb 2
194 amb 394 //static int boundsType_function(const char *_tag_,int _type_)
195     //{
196     // return(0);
197     //}
198 amb 2
199 amb 6
200 amb 394 /*++++++++++++++++++++++++++++++++++++++
201 amb 399 The function that is called when the boundType XSD type is seen
202    
203     int boundType_function Returns 0 if no error occured or something else otherwise.
204    
205     const char *_tag_ Set to the name of the element tag that triggered this function call.
206    
207     int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
208     ++++++++++++++++++++++++++++++++++++++*/
209    
210     //static int boundType_function(const char *_tag_,int _type_)
211     //{
212     // return(0);
213     //}
214    
215    
216     /*++++++++++++++++++++++++++++++++++++++
217 amb 394 The function that is called when the tagType XSD type is seen
218 amb 2
219 amb 394 int tagType_function Returns 0 if no error occured or something else otherwise.
220 amb 314
221 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
222 amb 2
223 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
224 amb 30
225 amb 394 const char *k The contents of the 'k' attribute (or NULL if not defined).
226 amb 30
227 amb 394 const char *v The contents of the 'v' attribute (or NULL if not defined).
228     ++++++++++++++++++++++++++++++++++++++*/
229 amb 30
230 amb 394 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
231     {
232 amb 401 if(_type_&XMLPARSE_TAG_START && current_tags)
233 amb 394 {
234     XMLPARSE_ASSERT_STRING(_tag_,k);
235     XMLPARSE_ASSERT_STRING(_tag_,v);
236 amb 30
237 amb 401 AppendTag(current_tags,k,v);
238 amb 394 }
239 amb 262
240 amb 394 return(0);
241     }
242 amb 308
243 amb 313
244 amb 394 /*++++++++++++++++++++++++++++++++++++++
245     The function that is called when the nodeType XSD type is seen
246 amb 313
247 amb 394 int nodeType_function Returns 0 if no error occured or something else otherwise.
248 amb 298
249 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
250 amb 298
251 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
252 amb 298
253 amb 394 const char *id The contents of the 'id' attribute (or NULL if not defined).
254 amb 298
255 amb 394 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
256 amb 298
257 amb 394 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
258     ++++++++++++++++++++++++++++++++++++++*/
259 amb 2
260 amb 394 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon)
261     {
262 amb 469 static node_t node_id;
263     static double latitude,longitude;
264    
265 amb 394 if(_type_&XMLPARSE_TAG_START)
266     {
267 amb 775 long long llid;
268 amb 394 nnodes++;
269    
270 amb 757 if(!(nnodes%10000))
271 amb 791 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
272 amb 2
273 amb 469 current_tags=NewTagList();
274    
275 amb 394 /* Handle the node information */
276 amb 2
277 amb 775 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
278     node_id=(node_t)llid;
279     assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
280    
281 amb 812 XMLPARSE_ASSERT_FLOATING(_tag_,lat); latitude =atof(lat);
282 amb 775 XMLPARSE_ASSERT_FLOATING(_tag_,lon); longitude=atof(lon);
283 amb 469 }
284 amb 2
285 amb 469 if(_type_&XMLPARSE_TAG_END)
286     {
287     TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
288 amb 2
289 amb 469 process_node_tags(result,node_id,latitude,longitude);
290    
291     DeleteTagList(current_tags);
292     DeleteTagList(result);
293 amb 394 }
294 amb 2
295 amb 394 return(0);
296     }
297 amb 2
298    
299 amb 394 /*++++++++++++++++++++++++++++++++++++++
300     The function that is called when the ndType XSD type is seen
301 amb 313
302 amb 394 int ndType_function Returns 0 if no error occured or something else otherwise.
303 amb 2
304 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
305 amb 297
306 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
307 amb 2
308 amb 394 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
309     ++++++++++++++++++++++++++++++++++++++*/
310 amb 2
311 amb 394 static int ndType_function(const char *_tag_,int _type_,const char *ref)
312     {
313     if(_type_&XMLPARSE_TAG_START)
314     {
315 amb 775 long long llid;
316 amb 394 node_t node_id;
317 amb 2
318 amb 775 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
319     node_id=(node_t)llid;
320     assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
321 amb 298
322 amb 498 if(way_nnodes && (way_nnodes%256)==0)
323 amb 394 way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
324 amb 8
325 amb 394 way_nodes[way_nnodes++]=node_id;
326     }
327 amb 51
328 amb 394 return(0);
329     }
330 amb 308
331 amb 298
332 amb 394 /*++++++++++++++++++++++++++++++++++++++
333     The function that is called when the memberType XSD type is seen
334 amb 298
335 amb 394 int memberType_function Returns 0 if no error occured or something else otherwise.
336 amb 298
337 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
338 amb 183
339 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
340 amb 298
341 amb 394 const char *type The contents of the 'type' attribute (or NULL if not defined).
342 amb 183
343 amb 394 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
344 amb 298
345 amb 394 const char *role The contents of the 'role' attribute (or NULL if not defined).
346     ++++++++++++++++++++++++++++++++++++++*/
347 amb 183
348 amb 498 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
349     {
350     if(_type_&XMLPARSE_TAG_START)
351     {
352 amb 775 long long llid;
353    
354 amb 498 XMLPARSE_ASSERT_STRING(_tag_,type);
355 amb 775 XMLPARSE_ASSERT_INTEGER(_tag_,ref); llid=atoll(ref); /* need long long conversion */
356 amb 298
357 amb 498 if(!strcmp(type,"node"))
358     {
359 amb 775 node_t node_id;
360 amb 298
361 amb 775 node_id=(node_t)llid;
362     assert((long long)node_id==llid); /* check node id can be stored in node_t data type. */
363    
364 amb 498 if(relation_nnodes && (relation_nnodes%256)==0)
365     relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
366    
367     relation_nodes[relation_nnodes++]=node_id;
368 amb 540
369     if(role)
370     {
371     if(!strcmp(role,"via"))
372     relation_via=node_id;
373     }
374 amb 498 }
375     else if(!strcmp(type,"way"))
376     {
377 amb 775 way_t way_id;
378 amb 498
379 amb 775 way_id=(way_t)llid;
380     assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
381    
382 amb 498 if(relation_nways && (relation_nways%256)==0)
383     relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
384    
385     relation_ways[relation_nways++]=way_id;
386 amb 540
387     if(role)
388     {
389     if(!strcmp(role,"from"))
390     relation_from=way_id;
391     if(!strcmp(role,"to"))
392     relation_to=way_id;
393     }
394 amb 498 }
395     else if(!strcmp(type,"relation"))
396     {
397 amb 775 relation_t relation_id;
398 amb 498
399 amb 775 relation_id=(relation_t)llid;
400     assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
401    
402 amb 498 if(relation_nrelations && (relation_nrelations%256)==0)
403     relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
404    
405     relation_relations[relation_nrelations++]=relation_id;
406     }
407     }
408    
409     return(0);
410     }
411    
412    
413 amb 394 /*++++++++++++++++++++++++++++++++++++++
414     The function that is called when the wayType XSD type is seen
415 amb 298
416 amb 394 int wayType_function Returns 0 if no error occured or something else otherwise.
417 amb 298
418 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
419 amb 51
420 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
421 amb 51
422 amb 394 const char *id The contents of the 'id' attribute (or NULL if not defined).
423     ++++++++++++++++++++++++++++++++++++++*/
424 amb 51
425 amb 394 static int wayType_function(const char *_tag_,int _type_,const char *id)
426     {
427     static way_t way_id;
428 amb 299
429 amb 394 if(_type_&XMLPARSE_TAG_START)
430     {
431 amb 775 long long llid;
432    
433 amb 394 nways++;
434 amb 51
435 amb 394 if(!(nways%1000))
436 amb 791 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
437 amb 51
438 amb 401 current_tags=NewTagList();
439 amb 498
440 amb 394 way_nnodes=0;
441 amb 298
442 amb 394 /* Handle the way information */
443 amb 313
444 amb 775 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
445    
446     way_id=(way_t)llid;
447     assert((long long)way_id==llid); /* check way id can be stored in way_t data type. */
448 amb 394 }
449 amb 196
450 amb 394 if(_type_&XMLPARSE_TAG_END)
451     {
452 amb 401 TagList *result=ApplyTaggingRules(&WayRules,current_tags);
453 amb 314
454 amb 394 process_way_tags(result,way_id);
455 amb 2
456 amb 401 DeleteTagList(current_tags);
457 amb 394 DeleteTagList(result);
458     }
459    
460     return(0);
461     }
462    
463    
464     /*++++++++++++++++++++++++++++++++++++++
465     The function that is called when the relationType XSD type is seen
466    
467     int relationType_function Returns 0 if no error occured or something else otherwise.
468    
469     const char *_tag_ Set to the name of the element tag that triggered this function call.
470    
471     int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
472    
473     const char *id The contents of the 'id' attribute (or NULL if not defined).
474     ++++++++++++++++++++++++++++++++++++++*/
475    
476     static int relationType_function(const char *_tag_,int _type_,const char *id)
477     {
478 amb 498 static relation_t relation_id;
479    
480 amb 394 if(_type_&XMLPARSE_TAG_START)
481     {
482 amb 775 long long llid;
483    
484 amb 394 nrelations++;
485    
486     if(!(nrelations%1000))
487 amb 791 printf_middle("Reading: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
488 amb 394
489 amb 498 current_tags=NewTagList();
490    
491     relation_nnodes=relation_nways=relation_nrelations=0;
492    
493 amb 755 relation_from=NO_WAY_ID;
494     relation_to=NO_WAY_ID;
495     relation_via=NO_NODE_ID;
496 amb 540
497 amb 498 /* Handle the relation information */
498    
499 amb 775 XMLPARSE_ASSERT_INTEGER(_tag_,id); llid=atoll(id); /* need long long conversion */
500    
501     relation_id=(relation_t)llid;
502     assert((long long)relation_id==llid); /* check relation id can be stored in relation_t data type. */
503 amb 2 }
504    
505 amb 498 if(_type_&XMLPARSE_TAG_END)
506     {
507     TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
508 amb 2
509 amb 498 process_relation_tags(result,relation_id);
510    
511     DeleteTagList(current_tags);
512     DeleteTagList(result);
513     }
514    
515 amb 2 return(0);
516     }
517    
518    
519     /*++++++++++++++++++++++++++++++++++++++
520 amb 394 The function that is called when the osmType XSD type is seen
521 amb 2
522 amb 394 int osmType_function Returns 0 if no error occured or something else otherwise.
523 amb 2
524 amb 394 const char *_tag_ Set to the name of the element tag that triggered this function call.
525 amb 2
526 amb 394 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
527     ++++++++++++++++++++++++++++++++++++++*/
528    
529     //static int osmType_function(const char *_tag_,int _type_)
530     //{
531     // return(0);
532     //}
533    
534    
535     /*++++++++++++++++++++++++++++++++++++++
536     The function that is called when the XML declaration is seen
537    
538     int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
539    
540     const char *_tag_ Set to the name of the element tag that triggered this function call.
541    
542     int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
543    
544     const char *version The contents of the 'version' attribute (or NULL if not defined).
545    
546     const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
547     ++++++++++++++++++++++++++++++++++++++*/
548    
549     //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
550     //{
551     // return(0);
552     //}
553    
554    
555     /*++++++++++++++++++++++++++++++++++++++
556     Parse an OSM XML file (from JOSM or planet download).
557    
558     int ParseOSM Returns 0 if OK or something else in case of an error.
559    
560 amb 2 FILE *file The file to read from.
561 amb 394
562 amb 498 NodesX *OSMNodes The data structure of nodes to fill in.
563 amb 394
564 amb 498 SegmentsX *OSMSegments The data structure of segments to fill in.
565 amb 394
566 amb 498 WaysX *OSMWays The data structure of ways to fill in.
567    
568     RelationsX *OSMRelations The data structure of relations to fill in.
569 amb 2 ++++++++++++++++++++++++++++++++++++++*/
570    
571 amb 498 int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations)
572 amb 2 {
573 amb 394 int retval;
574 amb 2
575 amb 498 /* Copy the function parameters and initialise the variables. */
576 amb 2
577 amb 394 nodes=OSMNodes;
578     segments=OSMSegments;
579     ways=OSMWays;
580 amb 498 relations=OSMRelations;
581 amb 394
582 amb 498 way_nodes=(node_t*)malloc(256*sizeof(node_t));
583    
584     relation_nodes =(node_t *)malloc(256*sizeof(node_t));
585     relation_ways =(way_t *)malloc(256*sizeof(way_t));
586     relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
587    
588     /* Parse the file */
589    
590 amb 394 nnodes=0,nways=0,nrelations=0;
591    
592 amb 519 printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
593 amb 394
594     retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
595    
596 amb 791 printf_last("Read: Lines=%llu Nodes=%"Pindex_t" Ways=%"Pindex_t" Relations=%"Pindex_t,ParseXML_LineNumber(),nnodes,nways,nrelations);
597 amb 394
598 amb 796 free(way_nodes);
599    
600     free(relation_nodes);
601     free(relation_ways);
602     free(relation_relations);
603    
604 amb 394 return(retval);
605     }
606    
607    
608     /*++++++++++++++++++++++++++++++++++++++
609 amb 469 Process the tags associated with a node.
610    
611     TagList *tags The list of node tags.
612    
613     node_t id The id of the node.
614    
615     double latitude The latitude of the node.
616    
617     double longitude The longitude of the node.
618     ++++++++++++++++++++++++++++++++++++++*/
619    
620     static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude)
621     {
622 amb 529 transports_t allow=Transports_ALL;
623 amb 538 uint16_t flags=0;
624 amb 469 int i;
625    
626     /* Parse the tags */
627    
628     for(i=0;i<tags->ntags;i++)
629     {
630     char *k=tags->k[i];
631     char *v=tags->v[i];
632    
633     switch(*k)
634     {
635     case 'b':
636     if(!strcmp(k,"bicycle"))
637 amb 812 {
638     if(ISFALSE(v))
639 amb 529 allow&=~Transports_Bicycle;
640 amb 812 else if(!ISTRUE(v))
641     logerror("Node %"Pnode_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v);
642     }
643 amb 469
644     break;
645    
646     case 'f':
647     if(!strcmp(k,"foot"))
648 amb 812 {
649     if(ISFALSE(v))
650 amb 529 allow&=~Transports_Foot;
651 amb 812 else if(!ISTRUE(v))
652     logerror("Node %"Pnode_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v);
653     }
654 amb 469
655     break;
656    
657     case 'g':
658     if(!strcmp(k,"goods"))
659 amb 812 {
660     if(ISFALSE(v))
661 amb 529 allow&=~Transports_Goods;
662 amb 812 else if(!ISTRUE(v))
663     logerror("Node %"Pnode_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v);
664     }
665 amb 469
666     break;
667    
668     case 'h':
669 amb 537 if(!strcmp(k,"highway"))
670     if(!strcmp(v,"mini_roundabout"))
671 amb 538 flags|=NODE_MINIRNDBT;
672 amb 537
673 amb 469 if(!strcmp(k,"horse"))
674 amb 812 {
675     if(ISFALSE(v))
676 amb 529 allow&=~Transports_Horse;
677 amb 812 else if(!ISTRUE(v))
678     logerror("Node %"Pnode_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v);
679     }
680 amb 469
681     if(!strcmp(k,"hgv"))
682 amb 812 {
683     if(ISFALSE(v))
684 amb 529 allow&=~Transports_HGV;
685 amb 812 else if(!ISTRUE(v))
686     logerror("Node %"Pnode_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v);
687     }
688 amb 469
689     break;
690    
691     case 'm':
692     if(!strcmp(k,"moped"))
693 amb 812 {
694     if(ISFALSE(v))
695 amb 529 allow&=~Transports_Moped;
696 amb 812 else if(!ISTRUE(v))
697     logerror("Node %"Pnode_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v);
698     }
699 amb 469
700     if(!strcmp(k,"motorbike"))
701 amb 812 {
702     if(ISFALSE(v))
703 amb 529 allow&=~Transports_Motorbike;
704 amb 812 else if(!ISTRUE(v))
705     logerror("Node %"Pnode_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v);
706     }
707 amb 469
708     if(!strcmp(k,"motorcar"))
709 amb 812 {
710     if(ISFALSE(v))
711 amb 529 allow&=~Transports_Motorcar;
712 amb 812 else if(!ISTRUE(v))
713     logerror("Node %"Pnode_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v);
714     }
715 amb 469
716     break;
717    
718     case 'p':
719     if(!strcmp(k,"psv"))
720 amb 812 {
721     if(ISFALSE(v))
722 amb 529 allow&=~Transports_PSV;
723 amb 812 else if(!ISTRUE(v))
724     logerror("Node %"Pnode_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v);
725     }
726 amb 469
727     break;
728    
729     case 'w':
730     if(!strcmp(k,"wheelchair"))
731 amb 812 {
732     if(ISFALSE(v))
733 amb 529 allow&=~Transports_Wheelchair;
734 amb 812 else if(!ISTRUE(v))
735     logerror("Node %"Pnode_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v);
736     }
737 amb 469
738     break;
739    
740     default:
741 amb 812 logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
742 amb 469 }
743     }
744    
745     /* Create the node */
746    
747 amb 538 AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags);
748 amb 469 }
749    
750    
751     /*++++++++++++++++++++++++++++++++++++++
752 amb 394 Process the tags associated with a way.
753    
754     TagList *tags The list of way tags.
755    
756     way_t id The id of the way.
757     ++++++++++++++++++++++++++++++++++++++*/
758    
759     static void process_way_tags(TagList *tags,way_t id)
760     {
761     Way way={0};
762 amb 536 int oneway=0;
763 amb 812 char *name=NULL,*ref=NULL,*refname=NULL;
764 amb 394 int i;
765    
766     /* Parse the tags */
767    
768     for(i=0;i<tags->ntags;i++)
769 amb 2 {
770 amb 394 char *k=tags->k[i];
771     char *v=tags->v[i];
772 amb 2
773 amb 394 switch(*k)
774     {
775     case 'b':
776     if(!strcmp(k,"bicycle"))
777 amb 812 {
778 amb 394 if(ISTRUE(v))
779 amb 529 way.allow|= Transports_Bicycle;
780 amb 812 else if(!ISFALSE(v))
781     logerror("Way %"Pway_t" has an unrecognised tag value 'bicycle' = '%s' (after processing tagging rules).\n",id,v);
782     }
783 amb 394
784 amb 498 if(!strcmp(k,"bicycleroute"))
785 amb 812 {
786 amb 498 if(ISTRUE(v))
787     way.props|=Properties_BicycleRoute;
788 amb 812 else if(!ISFALSE(v))
789     logerror("Way %"Pway_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v);
790     }
791 amb 498
792 amb 394 if(!strcmp(k,"bridge"))
793 amb 812 {
794 amb 394 if(ISTRUE(v))
795     way.props|=Properties_Bridge;
796 amb 812 else if(!ISFALSE(v))
797     logerror("Way %"Pway_t" has an unrecognised tag value 'bridge' = '%s' (after processing tagging rules).\n",id,v);
798     }
799 amb 394
800 amb 2 break;
801 amb 394
802     case 'f':
803     if(!strcmp(k,"foot"))
804 amb 812 {
805 amb 394 if(ISTRUE(v))
806 amb 529 way.allow|= Transports_Foot;
807 amb 812 else if(!ISFALSE(v))
808     logerror("Way %"Pway_t" has an unrecognised tag value 'foot' = '%s' (after processing tagging rules).\n",id,v);
809     }
810 amb 394
811 amb 498 if(!strcmp(k,"footroute"))
812 amb 812 {
813 amb 498 if(ISTRUE(v))
814     way.props|=Properties_FootRoute;
815 amb 812 else if(!ISFALSE(v))
816     logerror("Way %"Pway_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v);
817     }
818 amb 498
819 amb 394 break;
820    
821     case 'g':
822     if(!strcmp(k,"goods"))
823 amb 812 {
824 amb 394 if(ISTRUE(v))
825 amb 529 way.allow|=Transports_Goods;
826 amb 812 else if(!ISFALSE(v))
827     logerror("Way %"Pway_t" has an unrecognised tag value 'goods' = '%s' (after processing tagging rules).\n",id,v);
828     }
829 amb 394
830     break;
831    
832     case 'h':
833     if(!strcmp(k,"highway"))
834 amb 812 {
835 amb 394 way.type=HighwayType(v);
836    
837 amb 812 if(way.type==Way_Count)
838     logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after processing tagging rules).\n",id,v);
839     }
840    
841 amb 394 if(!strcmp(k,"horse"))
842 amb 812 {
843 amb 394 if(ISTRUE(v))
844 amb 529 way.allow|=Transports_Horse;
845 amb 812 else if(!ISFALSE(v))
846     logerror("Way %"Pway_t" has an unrecognised tag value 'horse' = '%s' (after processing tagging rules).\n",id,v);
847     }
848 amb 394
849     if(!strcmp(k,"hgv"))
850 amb 812 {
851 amb 394 if(ISTRUE(v))
852 amb 529 way.allow|=Transports_HGV;
853 amb 812 else if(!ISFALSE(v))
854     logerror("Way %"Pway_t" has an unrecognised tag value 'hgv' = '%s' (after processing tagging rules).\n",id,v);
855     }
856 amb 394
857     break;
858    
859     case 'm':
860     if(!strcmp(k,"maxspeed"))
861 amb 812 way.speed=kph_to_speed(parse_speed(id,k,v));
862 amb 394
863     if(!strcmp(k,"maxweight"))
864 amb 812 way.weight=tonnes_to_weight(parse_weight(id,k,v));
865 amb 394
866     if(!strcmp(k,"maxheight"))
867 amb 812 way.height=metres_to_height(parse_length(id,k,v));
868 amb 394
869     if(!strcmp(k,"maxwidth"))
870 amb 812 way.width=metres_to_height(parse_length(id,k,v));
871 amb 394
872     if(!strcmp(k,"maxlength"))
873 amb 812 way.length=metres_to_height(parse_length(id,k,v));
874 amb 394
875     if(!strcmp(k,"moped"))
876 amb 812 {
877 amb 394 if(ISTRUE(v))
878 amb 529 way.allow|=Transports_Moped;
879 amb 812 else if(!ISFALSE(v))
880     logerror("Way %"Pway_t" has an unrecognised tag value 'moped' = '%s' (after processing tagging rules).\n",id,v);
881     }
882 amb 394
883     if(!strcmp(k,"motorbike"))
884 amb 812 {
885 amb 394 if(ISTRUE(v))
886 amb 529 way.allow|=Transports_Motorbike;
887 amb 812 else if(!ISFALSE(v))
888     logerror("Way %"Pway_t" has an unrecognised tag value 'motorbike' = '%s' (after processing tagging rules).\n",id,v);
889     }
890 amb 394
891     if(!strcmp(k,"motorcar"))
892 amb 812 {
893 amb 394 if(ISTRUE(v))
894 amb 529 way.allow|=Transports_Motorcar;
895 amb 812 else if(!ISFALSE(v))
896     logerror("Way %"Pway_t" has an unrecognised tag value 'motorcar' = '%s' (after processing tagging rules).\n",id,v);
897     }
898 amb 394
899     if(!strcmp(k,"multilane"))
900 amb 812 {
901 amb 394 if(ISTRUE(v))
902     way.props|=Properties_Multilane;
903 amb 812 else if(!ISFALSE(v))
904     logerror("Way %"Pway_t" has an unrecognised tag value 'multilane' = '%s' (after processing tagging rules).\n",id,v);
905     }
906 amb 394
907     break;
908    
909     case 'n':
910     if(!strcmp(k,"name"))
911     name=v;
912    
913     break;
914    
915     case 'o':
916     if(!strcmp(k,"oneway"))
917     {
918     if(ISTRUE(v))
919     oneway=1;
920     else if(!strcmp(v,"-1"))
921     oneway=-1;
922 amb 812 else if(!ISFALSE(v))
923     logerror("Way %"Pway_t" has an unrecognised tag value 'oneway' = '%s' (after processing tagging rules).\n",id,v);
924 amb 394 }
925    
926     break;
927    
928     case 'p':
929     if(!strcmp(k,"paved"))
930 amb 812 {
931 amb 394 if(ISTRUE(v))
932     way.props|=Properties_Paved;
933 amb 812 else if(!ISFALSE(v))
934     logerror("Way %"Pway_t" has an unrecognised tag value 'paved' = '%s' (after processing tagging rules).\n",id,v);
935     }
936 amb 394
937     if(!strcmp(k,"psv"))
938 amb 812 {
939 amb 394 if(ISTRUE(v))
940 amb 529 way.allow|=Transports_PSV;
941 amb 812 else if(!ISFALSE(v))
942     logerror("Way %"Pway_t" has an unrecognised tag value 'psv' = '%s' (after processing tagging rules).\n",id,v);
943     }
944 amb 394
945     break;
946    
947     case 'r':
948     if(!strcmp(k,"ref"))
949     ref=v;
950    
951     break;
952    
953     case 't':
954     if(!strcmp(k,"tunnel"))
955 amb 812 {
956 amb 394 if(ISTRUE(v))
957     way.props|=Properties_Tunnel;
958 amb 812 else if(!ISFALSE(v))
959     logerror("Way %"Pway_t" has an unrecognised tag value 'tunnel' = '%s' (after processing tagging rules).\n",id,v);
960     }
961 amb 394
962     break;
963    
964     case 'w':
965     if(!strcmp(k,"wheelchair"))
966 amb 812 {
967 amb 394 if(ISTRUE(v))
968 amb 529 way.allow|=Transports_Wheelchair;
969 amb 812 else if(!ISFALSE(v))
970     logerror("Way %"Pway_t" has an unrecognised tag value 'wheelchair' = '%s' (after processing tagging rules).\n",id,v);
971     }
972 amb 394
973     break;
974    
975     default:
976 amb 812 logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
977 amb 394 }
978 amb 2 }
979    
980 amb 394 /* Create the way */
981 amb 2
982 amb 812 if(way.type==0 || way.type==Way_Count)
983     return;
984    
985     if(!way.allow)
986     return;
987    
988     if(way_nnodes==0)
989 amb 394 {
990 amb 812 logerror("Way %"Pway_t" has no nodes.\n",id);
991 amb 394
992 amb 812 return;
993     }
994 amb 394
995 amb 812 if(oneway)
996     way.type|=Way_OneWay;
997 amb 394
998 amb 812 if(ref && name)
999     {
1000     refname=(char*)malloc(strlen(ref)+strlen(name)+4);
1001     sprintf(refname,"%s (%s)",name,ref);
1002     }
1003     else if(ref && !name)
1004     refname=ref;
1005     else if(!ref && name)
1006     refname=name;
1007     else /* if(!ref && !name) */
1008     refname="";
1009 amb 394
1010 amb 812 AppendWay(ways,id,&way,refname);
1011 amb 394
1012 amb 812 if(ref && name)
1013     free(refname);
1014 amb 394
1015 amb 812 for(i=1;i<way_nnodes;i++)
1016     {
1017     node_t from=way_nodes[i-1];
1018     node_t to =way_nodes[i];
1019    
1020     if(oneway>0)
1021     AppendSegment(segments,id,from,to,ONEWAY_1TO2);
1022     else if(oneway<0)
1023     AppendSegment(segments,id,from,to,ONEWAY_2TO1);
1024     else
1025     AppendSegment(segments,id,from,to,0);
1026 amb 394 }
1027 amb 2 }
1028 amb 498
1029    
1030     /*++++++++++++++++++++++++++++++++++++++
1031     Process the tags associated with a relation.
1032    
1033     TagList *tags The list of relation tags.
1034    
1035     relation_t id The id of the relation.
1036     ++++++++++++++++++++++++++++++++++++++*/
1037    
1038     static void process_relation_tags(TagList *tags,relation_t id)
1039     {
1040 amb 529 transports_t routes=Transports_None;
1041 amb 540 transports_t except=Transports_None;
1042     int relation_turn_restriction=0;
1043 amb 541 TurnRestriction restriction=TurnRestrict_None;
1044 amb 498 int i;
1045    
1046     /* Parse the tags */
1047    
1048     for(i=0;i<tags->ntags;i++)
1049     {
1050     char *k=tags->k[i];
1051     char *v=tags->v[i];
1052    
1053     switch(*k)
1054     {
1055     case 'b':
1056     if(!strcmp(k,"bicycleroute"))
1057 amb 812 {
1058 amb 498 if(ISTRUE(v))
1059 amb 529 routes|=Transports_Bicycle;
1060 amb 812 else if(!ISFALSE(v))
1061     logerror("Relation %"Prelation_t" has an unrecognised tag value 'bicycleroute' = '%s' (after processing tagging rules).\n",id,v);
1062     }
1063 amb 498
1064     break;
1065    
1066 amb 540 case 'e':
1067     if(!strcmp(k,"except"))
1068 amb 812 {
1069 amb 540 for(i=1;i<Transport_Count;i++)
1070     if(!strstr(v,TransportName(i)))
1071     except|=TRANSPORTS(i);
1072    
1073 amb 812 if(except==Transports_None)
1074     logerror("Relation %"Prelation_t" has an unrecognised tag value 'except' = '%s' (after processing tagging rules).\n",id,v);
1075     }
1076    
1077 amb 540 break;
1078    
1079 amb 498 case 'f':
1080     if(!strcmp(k,"footroute"))
1081 amb 812 {
1082 amb 498 if(ISTRUE(v))
1083 amb 529 routes|=Transports_Foot;
1084 amb 812 else if(!ISFALSE(v))
1085     logerror("Relation %"Prelation_t" has an unrecognised tag value 'footroute' = '%s' (after processing tagging rules).\n",id,v);
1086     }
1087 amb 498
1088     break;
1089    
1090 amb 540 case 'r':
1091     if(!strcmp(k,"restriction"))
1092     {
1093 amb 541 if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn;
1094     if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn;
1095     if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn;
1096     if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on;
1097     if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn;
1098     if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn;
1099     if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on;
1100 amb 812
1101     if(restriction==TurnRestrict_None)
1102     logerror("Relation %"Prelation_t" has an unrecognised tag value 'restriction' = '%s' (after processing tagging rules).\n",id,v);
1103 amb 540 }
1104    
1105     break;
1106    
1107     case 't':
1108     if(!strcmp(k,"type"))
1109 amb 812 {
1110 amb 540 if(!strcmp(v,"restriction"))
1111     relation_turn_restriction=1;
1112 amb 812 else
1113     logerror("Relation %"Prelation_t" has an unrecognised tag value 'type' = '%s' (after processing tagging rules).\n",id,v);
1114     }
1115 amb 540 break;
1116    
1117 amb 498 default:
1118 amb 812 logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1119 amb 498 }
1120     }
1121    
1122 amb 505 /* Create the route relation (must store all relations that have ways or
1123     relations even if they are not routes because they might be referenced by
1124     other relations that are routes) */
1125 amb 498
1126 amb 540 if((relation_nways || relation_nrelations) && !relation_turn_restriction)
1127 amb 498 AppendRouteRelation(relations,id,routes,
1128     relation_ways,relation_nways,
1129     relation_relations,relation_nrelations);
1130 amb 540
1131     /* Create the turn restriction relation. */
1132    
1133 amb 812 if(relation_turn_restriction && restriction!=TurnRestrict_None)
1134     {
1135     if(relation_from==NO_WAY_ID)
1136     logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way (after processing tagging rules).\n",id);
1137     else if(relation_to==NO_WAY_ID)
1138     logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way (after processing tagging rules).\n",id);
1139     else if(relation_via==NO_NODE_ID)
1140     logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node (after processing tagging rules).\n",id);
1141     else
1142     AppendTurnRestrictRelation(relations,id,
1143     relation_from,relation_to,relation_via,
1144     restriction,except);
1145     }
1146 amb 498 }
1147 amb 812
1148    
1149     /*++++++++++++++++++++++++++++++++++++++
1150     Convert a string containing a speed into a double precision.
1151    
1152     double parse_speed Returns the speed in km/h if it can be parsed.
1153    
1154     way_t id The way being processed.
1155    
1156     const char *k The tag key.
1157    
1158     const char *v The tag value.
1159     ++++++++++++++++++++++++++++++++++++++*/
1160    
1161     static double parse_speed(way_t id,const char *k,const char *v)
1162     {
1163     char *ev;
1164     double value=strtod(v,&ev);
1165    
1166     if(v==ev)
1167     logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1168     else
1169     {
1170     while(isspace(*ev)) ev++;
1171    
1172     if(!strcmp(ev,"mph"))
1173     return(1.609*value);
1174     else if(*ev==0)
1175     return(value);
1176     else
1177     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1178     }
1179    
1180     return(0);
1181     }
1182    
1183    
1184     /*++++++++++++++++++++++++++++++++++++++
1185     Convert a string containing a weight into a double precision.
1186    
1187     double parse_weight Returns the weight in tonnes if it can be parsed.
1188    
1189     way_t id The way being processed.
1190    
1191     const char *k The tag key.
1192    
1193     const char *v The tag value.
1194     ++++++++++++++++++++++++++++++++++++++*/
1195    
1196     static double parse_weight(way_t id,const char *k,const char *v)
1197     {
1198     char *ev;
1199     double value=strtod(v,&ev);
1200    
1201     if(v==ev)
1202     logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1203     else
1204     {
1205     while(isspace(*ev)) ev++;
1206    
1207     if(!strcmp(ev,"kg"))
1208     return(value/1000.0);
1209     else if(*ev==0)
1210     return(value);
1211     else
1212     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1213     }
1214    
1215     return(0);
1216     }
1217    
1218    
1219     /*++++++++++++++++++++++++++++++++++++++
1220     Convert a string containing a length into a double precision.
1221    
1222     double parse_length Returns the length in metres if it can be parsed.
1223    
1224     way_t id The way being processed.
1225    
1226     const char *k The tag key.
1227    
1228     const char *v The tag value.
1229     ++++++++++++++++++++++++++++++++++++++*/
1230    
1231     static double parse_length(way_t id,const char *k,const char *v)
1232     {
1233     char *ev;
1234     double value=strtod(v,&ev);
1235    
1236     if(v==ev)
1237     logerror("Way %"Pway_t" has an unrecognised tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1238     else
1239     {
1240     int feet,inches;
1241     while(isspace(*ev)) ev++;
1242    
1243     if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
1244     return((feet+(double)inches/12.0)*0.254);
1245     else if(sscanf(v,"%d'",&feet)==1)
1246     return(feet*0.254);
1247     else if(!strcmp(ev,"ft") || !strcmp(ev,"feet"))
1248     return(value*0.254);
1249     else if(*ev==0)
1250     return(value);
1251     else
1252     logerror("Way %"Pway_t" has an un-parseable tag value '%s' = '%s' (after processing tagging rules).\n",id,k,v);
1253     }
1254    
1255     return(0);
1256     }

Properties

Name Value
cvs:description OSM XML file parser.