1 /***************************************
2  OSM file parser (either JOSM or planet)
3 
4  Part of the Routino routing software.
5  ******************/ /******************
6  This file Copyright 2008-2015 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 <stdlib.h>
24 #include <string.h>
25 #include <stdint.h>
26 
27 #include "types.h"
28 #include "typesx.h"
29 
30 #include "nodesx.h"
31 #include "waysx.h"
32 #include "relationsx.h"
33 
34 #include "osmparser.h"
35 #include "tagging.h"
36 #include "logging.h"
37 
38 
39 /* Local parsing variables (re-initialised for each file) */
40 
41 static NodesX     *nodes;
42 static WaysX      *ways;
43 static RelationsX *relations;
44 
45 static node_t     *way_nodes;
46 static int         way_nnodes;
47 
48 static node_t     *relation_nodes;
49 static int         relation_nnodes;
50 static way_t      *relation_ways;
51 static int         relation_nways;
52 static relation_t *relation_relations;
53 static int         relation_nrelations;
54 
55 
56 /*++++++++++++++++++++++++++++++++++++++
57   Initialise the OSM parser by initialising the local variables.
58 
59   NodesX *OSMNodes The data structure of nodes to fill in.
60 
61   WaysX *OSMWays The data structure of ways to fill in.
62 
63   RelationsX *OSMRelations The data structure of relations to fill in.
64   ++++++++++++++++++++++++++++++++++++++*/
65 
InitialiseParser(NodesX * OSMNodes,WaysX * OSMWays,RelationsX * OSMRelations)66 void InitialiseParser(NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations)
67 {
68  /* Copy the function parameters and initialise the variables */
69 
70  nodes=OSMNodes;
71  ways=OSMWays;
72  relations=OSMRelations;
73 
74  way_nodes=(node_t*)malloc(256*sizeof(node_t));
75 
76  relation_nodes    =(node_t    *)malloc(256*sizeof(node_t));
77  relation_ways     =(way_t     *)malloc(256*sizeof(way_t));
78  relation_relations=(relation_t*)malloc(256*sizeof(relation_t));
79 }
80 
81 
82 /*++++++++++++++++++++++++++++++++++++++
83   Clean up the memory after parsing.
84   ++++++++++++++++++++++++++++++++++++++*/
85 
CleanupParser(void)86 void CleanupParser(void)
87 {
88  /* Free the variables */
89 
90  free(way_nodes);
91 
92  free(relation_nodes);
93  free(relation_ways);
94  free(relation_relations);
95 }
96 
97 
98 /*++++++++++++++++++++++++++++++++++++++
99   Add node references to a way.
100 
101   int64_t node_id The node ID to add or zero to clear the list.
102   ++++++++++++++++++++++++++++++++++++++*/
103 
AddWayRefs(int64_t node_id)104 void AddWayRefs(int64_t node_id)
105 {
106  if(node_id==0)
107     way_nnodes=0;
108  else
109    {
110     node_t id;
111 
112     if(way_nnodes && (way_nnodes%256)==0)
113        way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t));
114 
115     id=(node_t)node_id;
116     logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */
117 
118     way_nodes[way_nnodes++]=id;
119    }
120 }
121 
122 
123 /*++++++++++++++++++++++++++++++++++++++
124   Add node, way or relation references to a relation.
125 
126   int64_t node_id The node ID to add or zero if it is not a node.
127 
128   int64_t way_id The way ID to add or zero if it is not a way.
129 
130   int64_t relation_id The relation ID to add or zero if it is not a relation.
131 
132   const char *role The role played by this referenced item or NULL.
133 
134   If all of node_id, way_id and relation_id are zero then the list is cleared.
135   ++++++++++++++++++++++++++++++++++++++*/
136 
AddRelationRefs(int64_t node_id,int64_t way_id,int64_t relation_id,const char * role)137 void AddRelationRefs(int64_t node_id,int64_t way_id,int64_t relation_id,const char *role)
138 {
139  if(node_id==0 && way_id==0 && relation_id==0)
140    {
141     relation_nnodes=0;
142     relation_nways=0;
143     relation_nrelations=0;
144    }
145  else if(node_id!=0)
146    {
147     node_t id;
148 
149     id=(node_t)node_id;
150     logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */
151 
152     if(relation_nnodes && (relation_nnodes%256)==0)
153        relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t));
154 
155     relation_nodes[relation_nnodes++]=id;
156    }
157  else if(way_id!=0)
158    {
159     way_t id;
160 
161     id=(way_t)way_id;
162     logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */
163 
164     if(relation_nways && (relation_nways%256)==0)
165        relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t));
166 
167     relation_ways[relation_nways++]=id;
168    }
169  else /* if(relation_id!=0) */
170    {
171     relation_t id;
172 
173     id=(relation_t)relation_id;
174     logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */
175 
176     if(relation_nrelations && (relation_nrelations%256)==0)
177        relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t));
178 
179     relation_relations[relation_nrelations++]=relation_id;
180    }
181 }
182 
183 
184 /*++++++++++++++++++++++++++++++++++++++
185   Process the tags associated with a node.
186 
187   TagList *tags The list of node tags.
188 
189   int64_t node_id The id of the node.
190 
191   double latitude The latitude of the node.
192 
193   double longitude The longitude of the node.
194 
195   int mode The mode of operation to take (create, modify, delete).
196   ++++++++++++++++++++++++++++++++++++++*/
197 
ProcessNodeTags(TagList * tags,int64_t node_id,double latitude,double longitude,int mode)198 void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode)
199 {
200  node_t id;
201  int i;
202 
203  /* Convert id */
204 
205  id=(node_t)node_id;
206  logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */
207 
208  /* Parse the tags */
209 
210  for(i=0;i<tags->ntags;i++)
211    {
212     char *k=tags->k[i];
213 
214     if(!strcmp(k,"fixme-finder:keep"))
215       {
216        DeleteTag(tags,"fixme-finder:keep");
217        logerror("<node id='%"Pnode_t"'>%s</node>\n",logerror_node(id),StringifyTag(tags));
218       }
219    }
220 
221  /* Store the node */
222 
223  AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),0,0);
224 }
225 
226 
227 /*++++++++++++++++++++++++++++++++++++++
228   Process the tags associated with a way.
229 
230   TagList *tags The list of way tags.
231 
232   int64_t way_id The id of the way.
233 
234   int mode The mode of operation to take (create, modify, delete).
235   ++++++++++++++++++++++++++++++++++++++*/
236 
ProcessWayTags(TagList * tags,int64_t way_id,int mode)237 void ProcessWayTags(TagList *tags,int64_t way_id,int mode)
238 {
239  Way way={0};
240  way_t id;
241  int i;
242 
243  /* Convert id */
244 
245  id=(way_t)way_id;
246  logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */
247 
248  /* Parse the tags */
249 
250  for(i=0;i<tags->ntags;i++)
251    {
252     char *k=tags->k[i];
253 
254     if(!strcmp(k,"fixme-finder:keep"))
255       {
256        DeleteTag(tags,"fixme-finder:keep");
257        logerror("<way id='%"Pway_t"'>%s</way>\n",logerror_way(id),StringifyTag(tags));
258       }
259    }
260 
261  /* Store the way */
262 
263  AppendWayList(ways,id,&way,way_nodes,way_nnodes,"");
264 }
265 
266 
267 /*++++++++++++++++++++++++++++++++++++++
268   Process the tags associated with a relation.
269 
270   TagList *tags The list of relation tags.
271 
272   int64_t relation_id The id of the relation.
273 
274   int mode The mode of operation to take (create, modify, delete).
275   ++++++++++++++++++++++++++++++++++++++*/
276 
ProcessRelationTags(TagList * tags,int64_t relation_id,int mode)277 void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode)
278 {
279  relation_t id;
280  int i;
281 
282  /* Convert id */
283 
284  id=(relation_t)relation_id;
285  logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */
286 
287  /* Parse the tags */
288 
289  for(i=0;i<tags->ntags;i++)
290    {
291     char *k=tags->k[i];
292 
293     if(!strcmp(k,"fixme-finder:keep"))
294       {
295        DeleteTag(tags,"fixme-finder:keep");
296        logerror("<relation id='%"Prelation_t"'>%s</relation>\n",logerror_relation(id),StringifyTag(tags));
297       }
298    }
299 
300  /* Store the relation */
301 
302  AppendRouteRelationList(relations,id,0,
303                          relation_nodes,relation_nnodes,
304                          relation_ways,relation_nways,
305                          relation_relations,relation_nrelations);
306 }
307