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 244 - (hide annotations) (download) (as text)
Thu Aug 20 18:38:41 2009 UTC (15 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 18440 byte(s)
Fix bug with memory allocation.

1 amb 2 /***************************************
2 amb 244 $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.48 2009-08-20 18:38:41 amb Exp $
3 amb 2
4     OSM XML file parser (either JOSM or planet)
5 amb 151
6     Part of the Routino routing software.
7 amb 2 ******************/ /******************
8 amb 151 This file Copyright 2008,2009 Andrew M. Bishop
9 amb 2
10 amb 151 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 amb 2 ***************************************/
23    
24    
25     #include <stdio.h>
26     #include <stdlib.h>
27     #include <string.h>
28     #include <ctype.h>
29    
30 amb 199 #include "typesx.h"
31     #include "functionsx.h"
32 amb 109 #include "nodesx.h"
33     #include "segmentsx.h"
34     #include "waysx.h"
35 amb 228 #include "ways.h"
36 amb 2
37 amb 26
38 amb 228 /*+ The length of the buffer and the size increment for reading lines from the file. +*/
39 amb 244 #define BUFFSIZE 256
40 amb 2
41 amb 228 /* Local functions */
42    
43 amb 2 static char *fgets_realloc(char *buffer,FILE *file);
44    
45    
46     /*++++++++++++++++++++++++++++++++++++++
47     Parse an OSM XML file (from JOSM or planet download).
48    
49     int ParseXML Returns 0 if OK or something else in case of an error.
50    
51     FILE *file The file to read from.
52 amb 26
53 amb 97 NodesX *OSMNodes The array of nodes to fill in.
54 amb 26
55 amb 97 SegmentsX *OSMSegments The array of segments to fill in.
56 amb 26
57 amb 97 WaysX *OSMWays The arrray of ways to fill in.
58 amb 75
59 amb 228 Profile *profile A profile of the allowed transport types and included/excluded highway types.
60 amb 2 ++++++++++++++++++++++++++++++++++++++*/
61    
62 amb 97 int ParseXML(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,Profile *profile)
63 amb 2 {
64     char *line=NULL;
65     long nlines=0;
66     long nnodes=0,nways=0,nrelations=0;
67     int isnode=0,isway=0,isrelation=0;
68 amb 203 way_t way_id=0;
69 amb 6 int way_oneway=0,way_roundabout=0;
70 amb 51 speed_t way_maxspeed=0;
71 amb 136 weight_t way_maxweight=0;
72     height_t way_maxheight=0;
73     width_t way_maxwidth=0;
74     length_t way_maxlength=0;
75 amb 51 char *way_highway=NULL,*way_name=NULL,*way_ref=NULL;
76     wayallow_t way_allow_no=0,way_allow_yes=0;
77 amb 2 node_t *way_nodes=NULL;
78     int way_nnodes=0,way_nalloc=0;
79    
80 amb 227 printf("\rReading: Lines=0 Nodes=0 Ways=0 Relations=0");
81     fflush(stdout);
82    
83 amb 2 /* Parse the file */
84    
85     while((line=fgets_realloc(line,file)))
86     {
87     char *l=line,*m;
88    
89     nlines++;
90    
91     while(isspace(*l))
92     l++;
93    
94     if(!strncmp(l,"<node",5)) /* The start of a node */
95     {
96     node_t id;
97 amb 219 double latitude,longitude;
98 amb 2
99     nnodes++;
100    
101     isnode=1; isway=0; isrelation=0;
102    
103     m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
104 amb 198 m=strstr(l,"lat="); m+=5; if(*m=='"' || *m=='\'') m++; latitude=degrees_to_radians(atof(m));
105     m=strstr(l,"lon="); m+=4; if(*m=='"' || *m=='\'') m++; longitude=degrees_to_radians(atof(m));
106 amb 2
107 amb 26 AppendNode(OSMNodes,id,latitude,longitude);
108 amb 159
109     if(strstr(l,"/>")) /* The end of a node */
110     {
111     isnode=0; isway=0; isrelation=0;
112     }
113 amb 2 }
114     else if(!strncmp(l,"</node",6)) /* The end of a node */
115     {
116     isnode=0; isway=0; isrelation=0;
117     }
118     else if(!strncmp(l,"<way",4)) /* The start of a way */
119     {
120     nways++;
121    
122     isnode=0; isway=1; isrelation=0;
123    
124 amb 203 m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; way_id=atoll(m);
125    
126 amb 51 way_oneway=0; way_roundabout=0;
127 amb 136 way_maxspeed=0; way_maxweight=0; way_maxheight=0; way_maxwidth=0;
128     way_maxlength=0;
129 amb 51 way_highway=NULL; way_name=NULL; way_ref=NULL;
130     way_allow_no=0; way_allow_yes=0;
131 amb 2 way_nnodes=0;
132     }
133     else if(!strncmp(l,"</way",5)) /* The end of a way */
134     {
135     isnode=0; isway=0; isrelation=0;
136    
137 amb 30 if(way_highway)
138 amb 2 {
139 amb 73 waytype_t type;
140 amb 75 wayallow_t allow;
141 amb 2
142 amb 74 type=HighwayType(way_highway);
143 amb 6
144 amb 75 switch(type)
145 amb 2 {
146 amb 75 case Way_Motorway:
147     allow=Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
148     break;
149     case Way_Trunk:
150     allow=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
151     break;
152     case Way_Primary:
153     allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
154     break;
155     case Way_Secondary:
156     allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
157     break;
158     case Way_Tertiary:
159     allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
160     break;
161 amb 85 case Way_Unclassified:
162 amb 75 allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
163     break;
164     case Way_Residential:
165     allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
166     break;
167     case Way_Service:
168     allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV;
169     break;
170     case Way_Track:
171 amb 78 allow=Allow_Foot|Allow_Bicycle|Allow_Horse;
172 amb 75 break;
173 amb 148 case Way_Path:
174     allow=Allow_Foot; /* Only allow bicycle and horse if so indicated. */
175     break;
176 amb 75 case Way_Bridleway:
177     allow=Allow_Foot|Allow_Bicycle|Allow_Horse;
178     break;
179     case Way_Cycleway:
180     allow=Allow_Foot|Allow_Bicycle;
181     break;
182     case Way_Footway:
183     allow=Allow_Foot;
184     break;
185 amb 92 default:
186     allow=0;
187     break;
188 amb 75 }
189    
190     if(way_allow_no) /* Remove the ones explicitly denied (e.g. private) */
191     allow&=~way_allow_no;
192    
193     if(way_allow_yes) /* Add the ones explicitly allowed (e.g. footpath along private) */
194     allow|=way_allow_yes;
195    
196 amb 166 if(allow&profile->allow && profile->highway[HIGHWAY(type)])
197 amb 75 {
198 amb 98 Way *way;
199 amb 87 char *refname;
200     int i;
201    
202 amb 73 if(way_ref && way_name)
203     {
204     refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4);
205     sprintf(refname,"%s (%s)",way_name,way_ref);
206     }
207     else if(way_ref && !way_name && way_roundabout)
208     {
209     refname=(char*)malloc(strlen(way_ref)+14);
210     sprintf(refname,"%s (roundabout)",way_ref);
211     }
212     else if(way_ref && !way_name)
213     refname=way_ref;
214     else if(!way_ref && way_name)
215     refname=way_name;
216     else if(way_roundabout)
217     {
218     refname=(char*)malloc(strlen(way_highway)+14);
219     sprintf(refname,"%s (roundabout)",way_highway);
220     }
221     else /* if(!way_ref && !way_name && !way_roundabout) */
222     refname=way_highway;
223 amb 2
224 amb 203 way=AppendWay(OSMWays,way_id,refname);
225 amb 2
226 amb 136 way->speed=way_maxspeed;
227     way->weight=way_maxweight;
228     way->height=way_maxheight;
229     way->width=way_maxwidth;
230     way->length=way_maxlength;
231 amb 30
232 amb 98 way->type=type;
233 amb 30
234 amb 98 way->allow=allow;
235 amb 51
236 amb 73 if(way_oneway)
237 amb 98 way->type|=Way_OneWay;
238 amb 30
239 amb 73 if(way_roundabout)
240 amb 98 way->type|=Way_Roundabout;
241 amb 30
242 amb 73 if(refname!=way_ref && refname!=way_name && refname!=way_highway)
243     free(refname);
244 amb 87
245     for(i=1;i<way_nnodes;i++)
246     {
247     node_t from=way_nodes[i-1];
248     node_t to =way_nodes[i];
249    
250 amb 117 if(way_oneway>0)
251 amb 209 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_1TO2);
252 amb 117 else if(way_oneway<0)
253 amb 209 AppendSegment(OSMSegments,way_id,from,to,ONEWAY_2TO1);
254     else
255     AppendSegment(OSMSegments,way_id,from,to,0);
256 amb 87 }
257 amb 73 }
258 amb 2 }
259    
260 amb 51 if(way_highway) free(way_highway);
261     if(way_name) free(way_name);
262     if(way_ref) free(way_ref);
263 amb 2 }
264     else if(!strncmp(l,"<relation",9)) /* The start of a relation */
265     {
266     nrelations++;
267    
268     isnode=0; isway=0; isrelation=1;
269     }
270     else if(!strncmp(l,"</relation",10)) /* The end of a relation */
271     {
272     isnode=0; isway=0; isrelation=0;
273     }
274     else if(isnode) /* The middle of a node */
275     {
276     }
277     else if(isway) /* The middle of a way */
278     {
279     node_t id;
280    
281     if(!strncmp(l,"<nd",3)) /* The start of a node specifier */
282     {
283     m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m);
284    
285 amb 244 if(way_nnodes==way_nalloc)
286     way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=256)*sizeof(node_t));
287 amb 2
288     way_nodes[way_nnodes++]=id;
289     }
290    
291     if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */
292     {
293     char delimiter,*k="",*v="";
294    
295     m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m;
296     while(*m!=delimiter) m++; *m=0; l=m+1;
297    
298     m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m;
299     while(*m!=delimiter) m++; *m=0;
300    
301 amb 51 switch(*k)
302     {
303     case 'a':
304     if(!strcmp(k,"access"))
305 amb 136 {
306 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
307 amb 136 ;
308     else
309 amb 51 way_allow_no=~0;
310 amb 136 }
311 amb 51 break;
312 amb 2
313 amb 51 case 'b':
314     if(!strcmp(k,"bicycle"))
315     {
316 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
317 amb 51 way_allow_yes|=Allow_Bicycle;
318     else
319     way_allow_no|=Allow_Bicycle;
320     }
321     break;
322 amb 2
323 amb 51 case 'f':
324     if(!strcmp(k,"foot"))
325     {
326 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
327 amb 51 way_allow_yes|=Allow_Foot;
328     else
329     way_allow_no|=Allow_Foot;
330     }
331     break;
332 amb 2
333 amb 51 case 'g':
334     if(!strcmp(k,"goods"))
335     {
336 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
337 amb 51 way_allow_yes|=Allow_Goods;
338     else
339     way_allow_no|=Allow_Goods;
340     }
341     break;
342 amb 2
343 amb 51 case 'h':
344     if(!strcmp(k,"highway"))
345     {
346     if(!strncmp(v,"motorway",8)) way_oneway=1;
347 amb 2
348 amb 51 way_highway=strcpy((char*)malloc(strlen(v)+1),v);
349     }
350     if(!strcmp(k,"horse"))
351     {
352 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
353 amb 51 way_allow_yes|=Allow_Horse;
354     else
355     way_allow_no|=Allow_Horse;
356     }
357     if(!strcmp(k,"hgv"))
358     {
359 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
360 amb 51 way_allow_yes|=Allow_HGV;
361     else
362     way_allow_no|=Allow_HGV;
363     }
364     break;
365 amb 8
366 amb 51 case 'j':
367     if(!strcmp(k,"junction"))
368     if(!strcmp(v,"roundabout"))
369     {way_oneway=1; way_roundabout=1;}
370     break;
371    
372     case 'm':
373     if(!strcmp(k,"maxspeed"))
374     {
375     if(strstr(v,"mph"))
376 amb 183 way_maxspeed=kph_to_speed(1.609*atof(v));
377 amb 136 else
378     way_maxspeed=kph_to_speed(atof(v));
379 amb 51 }
380 amb 183 if(!strcmp(k,"maxspeed:mph"))
381     way_maxspeed=kph_to_speed(1.609*atof(v));
382 amb 136 if(!strcmp(k,"maxweight"))
383     {
384     if(strstr(v,"kg"))
385     way_maxweight=tonnes_to_weight(atof(v)/1000);
386     else
387     way_maxweight=tonnes_to_weight(atof(v));
388     }
389     if(!strcmp(k,"maxheight"))
390     {
391 amb 183 if(strchr(v,'\''))
392     {
393     int feet,inches;
394    
395     if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
396 amb 219 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
397 amb 183 else if(sscanf(v,"%d'",&feet)==1)
398 amb 219 way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254);
399 amb 183 }
400     else if(strstr(v,"ft") || strstr(v,"feet"))
401 amb 136 way_maxheight=metres_to_height(atof(v)*0.254);
402     else
403     way_maxheight=metres_to_height(atof(v));
404     }
405     if(!strcmp(k,"maxwidth"))
406     {
407 amb 183 if(strchr(v,'\''))
408     {
409     int feet,inches;
410    
411     if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
412 amb 219 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
413 amb 183 else if(sscanf(v,"%d'",&feet)==1)
414 amb 219 way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254);
415 amb 183 }
416     else if(strstr(v,"ft") || strstr(v,"feet"))
417 amb 136 way_maxwidth=metres_to_width(atof(v)*0.254);
418     else
419     way_maxwidth=metres_to_width(atof(v));
420     }
421     if(!strcmp(k,"maxlength"))
422     {
423 amb 183 if(strchr(v,'\''))
424     {
425     int feet,inches;
426    
427     if(sscanf(v,"%d'%d\"",&feet,&inches)==2)
428 amb 219 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
429 amb 183 else if(sscanf(v,"%d'",&feet)==1)
430 amb 219 way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254);
431 amb 183 }
432     else if(strstr(v,"ft") || strstr(v,"feet"))
433 amb 136 way_maxlength=metres_to_length(atof(v)*0.254);
434     else
435     way_maxlength=metres_to_length(atof(v));
436     }
437 amb 51 if(!strcmp(k,"motorbike"))
438     {
439 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
440 amb 51 way_allow_yes|=Allow_Motorbike;
441     else
442     way_allow_no|=Allow_Motorbike;
443     }
444     if(!strcmp(k,"motorcar"))
445     {
446 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
447 amb 51 way_allow_yes|=Allow_Motorcar;
448     else
449     way_allow_no|=Allow_Motorcar;
450     }
451 amb 196 if(!strcmp(k,"motor_vehicle"))
452     {
453     if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
454     way_allow_yes|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
455     else
456     way_allow_no|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
457     }
458 amb 51 break;
459    
460     case 'n':
461     if(!strcmp(k,"name"))
462     way_name=strcpy((char*)malloc(strlen(v)+1),v);
463     break;
464    
465     case 'o':
466     if(!strcmp(k,"oneway"))
467 amb 117 {
468     if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1"))
469 amb 51 way_oneway=1;
470 amb 117 else if(!strcmp(v,"-1"))
471     way_oneway=-1;
472     }
473 amb 51 break;
474    
475     case 'p':
476     if(!strcmp(k,"psv"))
477     {
478 amb 146 if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
479 amb 51 way_allow_yes|=Allow_PSV;
480     else
481     way_allow_no|=Allow_PSV;
482     }
483     break;
484    
485     case 'r':
486     if(!strcmp(k,"ref"))
487     way_ref=strcpy((char*)malloc(strlen(v)+1),v);
488     break;
489    
490 amb 196 case 'v':
491     if(!strcmp(k,"vehicle"))
492     {
493     if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated"))
494     way_allow_yes|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
495     else
496     way_allow_no|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV;
497     }
498     break;
499    
500 amb 51 default:
501     ;
502 amb 2 }
503     }
504     }
505     else if(isrelation) /* The middle of a relation */
506     {
507     }
508    
509     if(!(nlines%10000))
510     {
511     printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations);
512     fflush(stdout);
513     }
514     }
515    
516 amb 35 printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",nlines,nnodes,nways,nrelations);
517 amb 2 fflush(stdout);
518    
519 amb 97 if(line)
520     free(line);
521    
522 amb 2 if(way_nalloc)
523     free(way_nodes);
524    
525     return(0);
526     }
527    
528    
529     /*++++++++++++++++++++++++++++++++++++++
530     Call fgets and realloc the buffer as needed to get a whole line.
531    
532     char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
533    
534     char *buffer The current buffer.
535    
536     FILE *file The file to read from.
537     ++++++++++++++++++++++++++++++++++++++*/
538    
539     static char *fgets_realloc(char *buffer,FILE *file)
540     {
541     int n=0;
542     char *buf;
543    
544     if(!buffer)
545     buffer=(char*)malloc(BUFFSIZE+1);
546    
547     while((buf=fgets(&buffer[n],BUFFSIZE,file)))
548     {
549     int s=strlen(buf);
550     n+=s;
551    
552     if(buffer[n-1]=='\n')
553     break;
554     else
555     buffer=(char*)realloc(buffer,n+BUFFSIZE+1);
556     }
557    
558     if(!buf)
559     {free(buffer);buffer=NULL;}
560    
561     return(buffer);
562     }

Properties

Name Value
cvs:description OSM XML file parser.