]> err.no Git - mapper/blob - src/osm.c
79c349c881635e6c220cfa7c77da04f86e56c19f
[mapper] / src / osm.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 /*
22  * Utility to read OSM planet XML file and store it in a sqlite3 database.
23  * Reads in all nodes (if used, skips nodes outside bounding box)
24  * Special POI nodes are stored in POI table.
25  * Place POI nodes are stored in place table.
26  *
27  * Ways are read in and their data (name, type, etc) are stored 
28  * in way, way_name and way_ref tables.
29  * 
30  * Nodes used by they ways are stored in way_n2n table.
31  *
32  * ... 
33  *
34  */
35
36 #define _GNU_SOURCE
37
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <strings.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <math.h>
46 #include <glib.h>
47 #include <glib/gstdio.h>
48 #include <sqlite3.h>
49 #include <expat.h>
50 #include <bzlib.h>
51
52 #include "osm.h"
53 #include "latlon.h"
54 #include "db.h"
55
56 #if 0
57 #define VERBOSE
58 #endif
59 /* #define VERBOSE_KEYS */
60
61 #define FILE_BUFFER 65535
62
63 #define OSM_DB_FILE "osm-planet.db"
64
65 /* Store pre-mercator projected integers for lat/lon for nodes */
66 #define INTEGER_LATLON
67
68 static guint node_cnt=0;
69 static guint node_skip_cnt=0;
70 static guint noded_cnt=0;
71 static guint way_cnt=0;
72 static guint way_names=0;
73 static guint way_refs=0;
74
75 static guint dbnode_cnt=0;
76 static guint dbnoded_cnt=0;
77 static guint dbway_cnt=0;
78
79 static gboolean is_update=FALSE;
80 static XML_Parser xp;
81
82 /* POI or Place node extra data */
83 typedef struct _node_data node_data;
84 struct _node_data {
85         gchar *name;
86         guint32 isin;
87 };
88
89 /* Node type */
90 typedef struct _node node;
91 struct _node {
92         guint32 id;
93         gdouble lat;
94         gdouble lon;
95         node_type_t type;
96         node_data *data;
97 };
98
99 /* Way data structure */
100 typedef struct _way_data way_data;
101 struct _way_data {
102         gchar *name;
103         GHashTable *names;
104         gchar *ref;
105         gchar *int_ref;
106         guint32 isin;
107         guint speed;
108         gint8 layer;
109 };
110
111 /* Way structure */
112 typedef struct _way way;
113 struct _way {
114         guint32 id;
115         way_type_t type;
116         guint16 ncnt;
117         guint8 flags;
118         way_data *data;
119         GSList *nodes;
120 };
121
122 /* XML tag IDs */
123 typedef enum {
124         START,
125         IN_OSM_TAG,
126         IN_NODE_TAG,
127         IN_WNODE_TAG,
128         IN_WAY_TAG,
129         IN_KEY_TAG,
130         IN_BOUND_TAG,
131         IN_RELATION_TAG,
132         IN_MEMBER_TAG,
133         END,
134         ERROR
135 } tag_state_t;
136
137 /* Parent tag type */
138 typedef enum {
139         IS_NONE,
140         IS_NODE,
141         IS_WAY,
142         IS_RELATION
143 } tag_parent_t;
144
145 /* Node types table */
146 /* XXX: Add support for parent category */
147 struct _nodeinfo {
148         gchar *k, *v;
149         node_type_t type;
150 } nodeinfo[] = {
151         { "amenity", "fuel",            NODE_AMENITY_FUEL },
152         { "amenity", "parking",         NODE_AMENITY_PARKING },
153
154         { "amenity", "pub",                     NODE_AMENITY_PUB },
155         { "amenity", "biergarten",      NODE_AMENITY_PUB },
156         { "amenity", "cafe",            NODE_AMENITY_CAFE },
157         { "amenity", "fast_food",       NODE_AMENITY_FOOD },
158         { "amenity", "restaurant",      NODE_AMENITY_FOOD },
159
160         { "amenity", "telephone",       NODE_AMENITY_TELEPHONE },
161         { "amenity", "toilets",         NODE_AMENITY_WC },
162
163         { "amenity", "hospital",        NODE_AMENITY_HOSPITAL },
164         { "amenity", "doctors",         NODE_AMENITY_HOSPITAL },
165         { "amenity", "pharmacy",        NODE_AMENITY_PHARMACY },
166
167         { "amenity", "post_office",     NODE_AMENITY_POST },
168         { "amenity", "post_box",        NODE_AMENITY_POST_BOX },
169
170         { "amenity", "cinema",          NODE_AMENITY_CINEMA },
171         { "amenity", "theatre",         NODE_AMENITY_THEATRE },
172
173         { "amenity", "atm",                     NODE_AMENITY_ATM },
174         { "amenity", "bank",            NODE_AMENITY_BANK },
175
176         { "amenity", "police",          NODE_AMENITY_POLICE },
177         { "amenity", "speed_trap",      NODE_AMENITY_SPEEDCAM },
178         { "amenity", "speed_camera",    NODE_AMENITY_SPEEDCAM },
179         { "amenity", "speed camera",    NODE_AMENITY_SPEEDCAM },
180
181         { "amenity", "place_of_worship",NODE_AMENITY_POW },
182
183         { "amenity", "school",          NODE_AMENITY_SCHOOL },
184         { "amenity", "college",         NODE_AMENITY_COLLEGE },
185         { "amenity", "university",      NODE_AMENITY_COLLEGE },
186
187         { "amenity", "library", NODE_AMENITY_LIBRARY },
188         { "amenity", "townhall",        NODE_AMENITY_TOWNHALL },
189
190         { "amenity", "supermarket",     NODE_AMENITY_SHOP },
191         { "amenity", "shopping_centre", NODE_AMENITY_SHOP },
192         { "amenity", "shop",            NODE_AMENITY_SHOP },
193         { "amenity", "shops",           NODE_AMENITY_SHOP },
194         { "amenity", "shopping",        NODE_AMENITY_SHOP },
195         { "amenity", "shopping_mall",NODE_AMENITY_SHOP },
196         { "amenity", "cycle_shop",      NODE_AMENITY_SHOP },
197         { "amenity", "bike_shop",       NODE_AMENITY_SHOP },
198         { "amenity", "coffee_shop",     NODE_AMENITY_SHOP },
199         { "amenity", "indoor_shopping_centre",  NODE_AMENITY_SHOP },
200         { "amenity", "farm_shop",       NODE_AMENITY_SHOP },
201         { "amenity", "tea_shop",        NODE_AMENITY_SHOP },
202
203         /* Shops */
204         { "shop",        "supermarket", NODE_AMENITY_SHOP },
205         { "shop",        "bakery",              NODE_AMENITY_SHOP },
206         { "shop",        "alcohol",             NODE_AMENITY_SHOP }, 
207         { "shop",        "butcher",             NODE_AMENITY_SHOP },
208         { "shop",        "flowers",             NODE_AMENITY_SHOP },
209         { "shop",        "clothing",    NODE_AMENITY_SHOP },
210         { "shop",        "souvenir",    NODE_AMENITY_SHOP },
211         { "shop",        "bicycles",    NODE_AMENITY_SHOP },
212         { "shop",        "grocers",             NODE_AMENITY_SHOP },
213         { "shop",        "newsagents",  NODE_AMENITY_SHOP },
214         { "shop",        "convenience", NODE_AMENITY_SHOP },
215         { "shop",        "bakers",              NODE_AMENITY_SHOP },
216         { "shop",        "garden_centre",NODE_AMENITY_SHOP },
217         { "shop",        "photography", NODE_AMENITY_SHOP },
218         { "shop",        "general_store",NODE_AMENITY_SHOP },
219         { "shop",        "food",                NODE_AMENITY_SHOP },
220         { "shop",        "drinks",              NODE_AMENITY_SHOP },
221         { "shop",        "pharmacy",    NODE_AMENITY_PHARMACY },
222
223         /* Sport */
224         { "sport"  , "swimming",        NODE_SPORT_SWIMMING },
225         { "sport"  , "golf",            NODE_SPORT_GOLF },
226         { "sport"  , "tennis",          NODE_SPORT_TENNIS },
227         { "sport"  , "football",        NODE_SPORT_FOOTBALL },
228         { "sport"  , "soccer",          NODE_SPORT_SOCCER },
229         { "sport"  , "baskteball",      NODE_SPORT_BASKETBALL },
230         { "sport"  , "rugby",           NODE_SPORT_RUGBY },
231         { "sport"  , "skating",         NODE_SPORT_SKATING },
232         { "sport"  , "hockey",          NODE_SPORT_HOCKEY },
233         { "sport"  , "skateboard",      NODE_SPORT_SKATEBOARD },
234         { "sport"  , "bowling",         NODE_SPORT_BOWLING },
235         { "sport"  , "10pin",           NODE_SPORT_BOWLING },
236         { "sport"  , "motor",           NODE_SPORT_MOTOR },
237         { "sport"  , "shooting_range",NODE_SPORT_SHOOTING },
238         { "sport"  , "paintball",       NODE_SPORT_PAINTBALL },
239         { "sport"  , "horse_racing",NODE_SPORT_HORSES },
240         { "sport"  , "horse",           NODE_SPORT_HORSES },
241         { "sport"  , "horses",          NODE_SPORT_HORSES },
242         { "sport"  , "dog_racing",      NODE_SPORT_DOG },
243         { "sport"  , "pelota",          NODE_SPORT_PELOTA },
244         { "sport"  , "racquet",         NODE_SPORT_RACQUET },
245         { "sport"  , "equestrian",      NODE_SPORT_HORSES },
246         { "sport"  , "baseball",        NODE_SPORT_BASEBALL },
247         { "sport"  , "cricket",         NODE_SPORT_CRICKET },
248         { "sport"  , "croquet",         NODE_SPORT_CROQUET },
249         { "sport"  , "cycling",         NODE_SPORT_CYCLING },
250         { "sport"  , "bowls",           NODE_SPORT_BOWLS },
251         { "sport"  , "athletics",       NODE_SPORT_ATHLETICS },
252         { "sport"  , "gymnastics",      NODE_SPORT_GYMNASTICS },
253         { "sport"  , "multi",           NODE_SPORT_OTHER },
254         { "leisure", "sport_centre",NODE_SPORT_CENTER },
255
256         /* Tourism */
257         { "tourism", "information",     NODE_TOURISM_INFO },
258         { "tourism", "camp_site",       NODE_TOURISM_CAMP_SITE },
259         { "tourism", "caravan_site",NODE_TOURISM_CARAVAN_SITE },
260         { "tourism", "picnic_site",     NODE_TOURISM_PICNIC_SITE },
261         { "tourism", "theme_park",      NODE_TOURISM_THEME_PARK },
262         { "tourism", "hotel",           NODE_TOURISM_HOTEL },
263         { "tourism", "motel",           NODE_TOURISM_MOTEL },
264         { "tourism", "hostel",          NODE_TOURISM_HOSTEL },
265         { "tourism", "attraction",      NODE_TOURISM_ATTRACTION },
266         { "tourism", "zoo",                     NODE_TOURISM_ATTRACTION },
267
268         { "historic", "ruins",          NODE_TOURISM_ATTRACTION },
269         { "historic", "monument",       NODE_TOURISM_ATTRACTION },
270         { "historic", "memorial",       NODE_TOURISM_ATTRACTION },
271         { "historic", "museum",         NODE_HISTORIC_MUSEUM },
272         { "historic", "castle",         NODE_HISTORIC_CASTLE },
273
274         { "railway", "station",         NODE_RAILWAY_STATION },
275         { "railway", "halt",            NODE_RAILWAY_HALT },
276
277         { "aeroway", "terminal",        NODE_AIRPORT_TERMINAL },
278
279         /* Places */    
280         { "place", "city",                      NODE_PLACE_CITY },
281         { "place", "town",                      NODE_PLACE_TOWN },
282         { "place", "village",           NODE_PLACE_VILLAGE },
283         { "place", "hamlet",            NODE_PLACE_HAMLET },
284         { "place", "suburb",            NODE_PLACE_SUBURB },
285         { "place", "island",            NODE_PLACE_ISLAND },
286
287         { "highway", "traffic_signals", NODE_TRAFFIC_SIGNALS },
288         { "highway", "motorway_junction",       NODE_JUNCTION },
289         { "highway", "services",        NODE_AMENITY_PARKING },
290         { "highway", "toll_booth",      NODE_TOLLBOOTH },
291         { "highway", "gate",            NODE_GATE },
292
293         { NULL, NULL, NODE_PLAIN }
294 };
295
296 /* Array to get id number and defaults for ways of different types */
297 struct _wayinfo {
298         gchar *k, *v;
299         guint defspeed;
300         way_type_t type;
301         gboolean oneway, link, area, car, foot;
302 } wayinfo[] = {
303         { "highway", "motorway",120,WAY_MOTORWAY,               TRUE, FALSE, FALSE, TRUE, FALSE },
304         { "highway", "motorway_link",120,WAY_MOTORWAY,  TRUE, TRUE, FALSE, TRUE, FALSE },
305         { "highway", "trunk",100,WAY_TRUNK,                             FALSE, FALSE, FALSE, TRUE, FALSE },
306         { "highway", "trunk_link",100,WAY_TRUNK,                FALSE, TRUE, FALSE, TRUE, FALSE },
307         { "highway", "primary",80,WAY_PRIMARY,                  FALSE, FALSE, FALSE, TRUE, TRUE },
308         { "highway", "primary_link",60,WAY_PRIMARY,             FALSE, TRUE, FALSE, TRUE, TRUE },
309         { "highway", "secondary",80,WAY_SECONDARY,              FALSE, FALSE, FALSE, TRUE, TRUE },
310         { "highway", "secondary_link",60,WAY_SECONDARY, FALSE, TRUE, FALSE, TRUE, TRUE },
311         { "highway", "tertiary",60,WAY_TERTIARY,                FALSE, FALSE, FALSE, TRUE, TRUE },
312         { "highway", "unclassified",50,WAY_UNCLASSIFIED,        FALSE, FALSE, FALSE, TRUE, TRUE },
313         { "highway", "byway",40,WAY_UNCLASSIFIED,       FALSE, FALSE, FALSE, TRUE, TRUE },
314         { "highway", "residential",40,WAY_RESIDENTIAL,  FALSE, FALSE, FALSE, TRUE, TRUE },
315         { "highway", "service",20,WAY_SERVICE,                  FALSE, FALSE, FALSE, TRUE, TRUE },
316         { "highway", "track",20,WAY_TRACK,                              FALSE, FALSE, FALSE, TRUE, TRUE },
317         { "highway", "unsurfaced",60,WAY_TRACK,                 FALSE, FALSE, FALSE, TRUE, TRUE },
318         { "highway", "minor",60,WAY_TRACK,                      FALSE, FALSE, FALSE, TRUE, TRUE },
319         { "highway", "pedestrian",20,WAY_FOOTWAY,               FALSE, FALSE, FALSE, FALSE, TRUE },
320         { "highway", "footway",1,WAY_FOOTWAY,                   FALSE, FALSE, FALSE, FALSE, TRUE },
321         { "highway", "steps",0,WAY_FOOTWAY,                             FALSE, FALSE, FALSE, FALSE, TRUE},
322         { "highway", "bridleway",10,WAY_FOOTWAY,                FALSE, FALSE, FALSE, FALSE, TRUE },
323         { "highway", "cycleway",10,WAY_CYCLEWAY,                FALSE, FALSE, FALSE, FALSE, TRUE },
324         { "railway", "rail",0,WAY_RAIL,                                 FALSE, FALSE, FALSE, FALSE, FALSE },
325         { "aeroway", "runway",0,WAY_RUNWAY,                             FALSE, FALSE, FALSE, FALSE, FALSE },
326         { "aeroway", "taxiway",0,WAY_TAXIWAY,                   FALSE, FALSE, FALSE, FALSE, FALSE },
327         { "natural", "water",0,WAY_WATER,                               FALSE, FALSE, TRUE, FALSE, FALSE },
328         { "waterway", "river",0,WAY_WATER,                              FALSE, FALSE, FALSE, FALSE, FALSE },
329         { "waterway", "canal",0,WAY_WATER,                              FALSE, FALSE, FALSE, FALSE, FALSE },
330         { "waterway", "stream",0,WAY_WATER,                             FALSE, FALSE, FALSE, FALSE, FALSE },
331         { "building", "*",0,WAY_UNWAYED,                                FALSE, FALSE, TRUE, FALSE, FALSE },
332         { NULL, NULL, 0, WAY_UNWAYED, FALSE, FALSE, FALSE, FALSE, FALSE }
333 };
334
335 static sqlite3 *db;
336 tag_parent_t tag_parent=IS_NONE;
337
338 static GHashTable *osm_nodes;
339 static GHashTable *osm_node_tags;
340 static GHashTable *osm_way_tags;
341 static GSList *osm_ways;
342 static GSList *osm_poi;
343
344 static GHashTable *osm_place_country;
345 static GHashTable *osm_place_region;
346 static GHashTable *osm_place_city;
347 static GHashTable *osm_place_suburb;
348 static GHashTable *osm_place_village;
349 static GHashTable *osm_node_isin;
350 static GHashTable *osm_way_isin;
351
352 static node *cnode=NULL;
353 static way *cway=NULL;
354
355 struct sql_stmt {
356         sqlite3_stmt *insert_poi;
357         sqlite3_stmt *delete_osm_poi;
358
359         sqlite3_stmt *insert_node;
360         sqlite3_stmt *delete_nodes;
361         sqlite3_stmt *select_node;
362         sqlite3_stmt *update_node;
363
364         sqlite3_stmt *insert_way_data;
365         sqlite3_stmt *insert_way_ref;
366         sqlite3_stmt *insert_way_name;
367         sqlite3_stmt *insert_way_names_nls;
368         sqlite3_stmt *insert_way_n2n;
369         sqlite3_stmt *delete_way;
370         sqlite3_stmt *delete_way_n2n;
371         sqlite3_stmt *delete_way_seg_wsid;
372         sqlite3_stmt *delete_way_name;
373         sqlite3_stmt *delete_way_names_nls;
374         sqlite3_stmt *delete_way_ref;
375
376         sqlite3_stmt *insert_place;
377         sqlite3_stmt *delete_place;
378 };
379 static struct sql_stmt sql;
380
381 struct map_bbox {
382         gdouble lat_min;
383         gdouble lon_min;
384         gdouble lat_max;
385         gdouble lon_max;
386 };
387 static struct map_bbox bbox;
388 static gboolean use_bbox;
389
390 void osm_free_way_data(way *w);
391 void print_way(way *w);
392
393 void db_prepare(void);
394 gboolean db_insert_node(node *n);
395 guint32 osm_find_way_place(way *w);
396
397 /****************************************************/
398 /* Functions */
399 /****************************************************/
400
401 static void
402 db_finalize(void)
403 {
404 sqlite3_finalize(sql.insert_poi);
405 sqlite3_finalize(sql.delete_osm_poi);
406
407 sqlite3_finalize(sql.insert_node);
408 sqlite3_finalize(sql.select_node);
409 sqlite3_finalize(sql.delete_nodes);
410 sqlite3_finalize(sql.update_node);
411
412 sqlite3_finalize(sql.insert_place);
413 sqlite3_finalize(sql.delete_place);
414
415 sqlite3_finalize(sql.delete_way);
416 sqlite3_finalize(sql.insert_way_data);
417
418 sqlite3_finalize(sql.delete_way_name);
419 sqlite3_finalize(sql.insert_way_name);
420
421 sqlite3_finalize(sql.delete_way_n2n);
422 sqlite3_finalize(sql.insert_way_n2n);
423
424 sqlite3_finalize(sql.delete_way_names_nls);
425 sqlite3_finalize(sql.insert_way_names_nls);
426 }
427
428 void
429 db_prepare(void)
430 {
431 /* Way nodes */
432 sqlite3_prepare_v2(db, "insert or replace into nodes (nid,lat,lon,l,f) values (?,?,?,0,?)", -1, &sql.insert_node, NULL);
433 sqlite3_prepare_v2(db, "select lat,lon,l from nodes where nid=?", -1, &sql.select_node, NULL);
434 sqlite3_prepare_v2(db, "delete from nodes", -1, &sql.delete_nodes, NULL);
435 sqlite3_prepare_v2(db, "update nodes set l=l+1 where nid=?", -1, &sql.update_node, NULL);
436
437 /* Places */
438 sqlite3_prepare_v2(db, "insert or replace into places (nid,type,name,isin) values (?, ?, ?, ?)", -1, &sql.insert_place, NULL);
439 sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_place, NULL);
440
441 /* POI nodes */
442 sqlite3_prepare_v2(db, "insert or replace into poi (osm_id, lat, lon, label, cat_id, public, source, priority, isin, desc) values (?, ?, ?, ?, ?, 1, 1, ?, ?, ?)", 
443         -1, &sql.insert_poi, NULL);
444 sqlite3_prepare_v2(db, "delete from poi where osm_id>0", -1, &sql.delete_osm_poi, NULL);
445
446 /* Ways */
447 sqlite3_prepare_v2(db, "insert or replace into way (wid,nodes,type,flags,speed,isin) values (?, ?, ?, ?, ?, ?)", -1, &sql.insert_way_data, NULL);
448 sqlite3_prepare_v2(db, "delete from way", -1, &sql.delete_way, NULL);
449
450 /* Way nodes */
451 sqlite3_prepare_v2(db, "insert into way_n2n (wsid,f,t) values (?,?,?)", -1, &sql.insert_way_n2n, NULL);
452 sqlite3_prepare_v2(db, "delete from way_n2n where wsid=?", -1, &sql.delete_way_n2n, NULL);
453
454 /* Way names */
455 sqlite3_prepare_v2(db, "insert or replace into way_names (wid,name) values (?, ?)",  -1, &sql.insert_way_name, NULL);
456 sqlite3_prepare_v2(db, "delete from way_names", -1, &sql.delete_way_name, NULL);
457
458 /* Other language names for ways */
459 sqlite3_prepare_v2(db, "insert into way_names_nls (wid,lang,name) values (?, ?, ?)",  -1, &sql.insert_way_names_nls, NULL);
460 sqlite3_prepare_v2(db, "delete from way_names_nls where wid=?", -1, &sql.delete_way_names_nls, NULL);
461
462 /* Way ref and int_ref */
463 sqlite3_prepare_v2(db, "insert or replace into way_ref (rid,ref,int_ref) values (?, ?, ?)", -1, &sql.insert_way_ref, NULL);
464 sqlite3_prepare_v2(db, "delete from way_ref", -1, &sql.delete_way_ref, NULL);
465 }
466
467 /********************************************************************/
468
469 void
470 print_way(way *w)
471 {
472 #ifdef VERBOSE
473 g_assert(w);
474 g_printf("Way #%d(N:%d T:%d S:%d IS: %d): %s [%s:%s:%s]\n", 
475                 w->id,  
476                 g_slist_length(w->nodes), 
477                 w->type,
478                 w->data ? w->data->speed : 0,
479                 w->data ? w->data->isin : 0,
480                 w->data ? w->data->name ? w->data->name : "" : "", 
481                 w->flags & W_ONEWAY ? "-" : "=", 
482                 w->flags & W_ROUNDABOUT ? "O" : "-", 
483                 w->flags & W_LINK ? "|" : " ");
484 #endif
485 }
486
487 void
488 print_node(node *n)
489 {
490 #ifdef VERBOSE
491 g_assert(n);
492 g_printf("Node #%d: T:%d IS: %d [%s]\n",
493         n->id,
494         n->type,
495         n->data ? n->data->isin : 0,
496         n->data ? n->data->name : "");
497 #endif
498 }
499
500 /********************************************************************/
501
502 gboolean
503 db_insert_node(node *n)
504 {
505 gint32 lat, lon;
506
507 sqlite3_bind_int(sql.insert_node, 1, n->id);
508
509 #ifdef INTEGER_LATLON
510 lat=lat2mp_int(n->lat);
511 lon=lon2mp_int(n->lon);
512 sqlite3_bind_int(sql.insert_node, 2, lat);
513 sqlite3_bind_int(sql.insert_node, 3, lon);
514 #else
515 sqlite3_bind_double(sql.insert_node, 2, lat);
516 sqlite3_bind_double(sql.insert_node, 3, lon);
517 #endif
518
519 sqlite3_bind_int(sql.insert_node, 4, n->type);
520 sqlite3_step(sql.insert_node);
521 sqlite3_reset(sql.insert_node);
522 sqlite3_clear_bindings(sql.insert_node);
523
524 return TRUE;
525 }
526
527 static gboolean
528 db_insert_place(node *n)
529 {
530 if (!n->data)
531         return FALSE;
532 if (!n->data->name)
533         return FALSE;
534 sqlite3_bind_int(sql.insert_place, 1, n->id);
535 sqlite3_bind_int(sql.insert_place, 2, n->type);
536 sqlite3_bind_text(sql.insert_place, 3, n->data->name, -1, SQLITE_TRANSIENT);
537 sqlite3_bind_int(sql.insert_place, 4, n->data->isin);
538
539 return db_exec(sql.insert_place);
540 }
541
542 static gboolean
543 db_insert_poi(node *n)
544 {
545 sqlite3_bind_int(sql.insert_poi, 1, n->id);
546 sqlite3_bind_double(sql.insert_poi, 2, n->lat);
547 sqlite3_bind_double(sql.insert_poi, 3, n->lon);
548 if (n->data->name)
549         sqlite3_bind_text(sql.insert_poi, 4, n->data->name, -1, SQLITE_TRANSIENT);
550 else
551         sqlite3_bind_text(sql.insert_poi, 4, "", -1, SQLITE_TRANSIENT);
552 sqlite3_bind_int(sql.insert_poi, 5, n->type);
553 sqlite3_bind_int(sql.insert_poi, 6, n->type/100);
554 sqlite3_bind_int(sql.insert_poi, 7, n->data->isin);
555
556 #if 0
557 if (n->data->desc)
558         sqlite3_bind_text(sql.insert_poi, 8, n->data->desc, -1, SQLITE_TRANSIENT);
559 if (n->data->url)
560         sqlite3_bind_text(sql.insert_poi, 9, n->data->url, -1, SQLITE_TRANSIENT);
561 #endif
562
563 return db_exec(sql.insert_poi);
564 }
565
566 /**
567  * Update node usage count
568  */
569 static gboolean
570 db_update_node_links(node *n)
571 {
572 sqlite3_bind_int(sql.update_node, 1, n->id);
573
574 return db_exec(sql.update_node);
575 }
576
577 /**
578  * Insert way,node1,node2 triplet
579  */
580 static gboolean
581 db_insert_way_n2n(way *w, node *nf, node *nt)
582 {
583 if (!w) {
584         g_printf("NULL WAY\n");
585         return FALSE;
586 }
587
588 if (!nf) {
589         g_printf("NULL NODE 1\n");
590         return FALSE;
591 }
592
593 if (!nt) {
594         g_printf("NULL NODE 2\n");
595         return FALSE;
596 }
597
598 sqlite3_bind_int(sql.insert_way_n2n, 1, w->id);
599 sqlite3_bind_int(sql.insert_way_n2n, 2, nf->id);
600 sqlite3_bind_int(sql.insert_way_n2n, 3, nt->id);
601
602 #ifdef VERBOSE_N2N
603 g_printf("%d [%d - %d]\n", w->id, nf->id, nt->id);
604 #endif
605
606 db_exec(sql.insert_way_n2n);
607 db_update_node_links(nf);
608 db_update_node_links(nt);
609 return TRUE;
610 }
611
612 /**
613  * Insert way ref and int_ref
614  */
615 static void 
616 db_insert_way_ref(way *w)
617 {
618 if (!w->data)
619         return;
620
621 if (!w->data->ref && !w->data->int_ref)
622         return;
623
624 way_refs++;
625
626 sqlite3_bind_int(sql.insert_way_ref, 1, w->id);
627 if (w->data->ref)
628         sqlite3_bind_text(sql.insert_way_ref, 2, w->data->ref, -1, SQLITE_TRANSIENT);
629 if (w->data->int_ref)
630         sqlite3_bind_text(sql.insert_way_ref, 3, w->data->int_ref, -1, SQLITE_TRANSIENT);
631
632 db_exec(sql.insert_way_ref);
633 }
634
635 /**
636  * Insert way name
637  */
638 static void 
639 db_insert_way_name(way *w)
640 {
641 if (!w->data)
642         return;
643 if (!w->data->name)
644         return;
645
646 way_names++;
647
648 sqlite3_bind_int(sql.insert_way_name, 1, w->id);
649 sqlite3_bind_text(sql.insert_way_name, 2, w->data->name, -1, SQLITE_TRANSIENT);
650
651 db_exec(sql.insert_way_name);
652 }
653
654 static void
655 db_delete_way_names_nls(way *w)
656 {
657 sqlite3_bind_int(sql.delete_way_names_nls, 1, w->id);
658
659 sqlite3_step(sql.delete_way_names_nls);
660 sqlite3_reset(sql.delete_way_names_nls);
661 sqlite3_clear_bindings(sql.delete_way_names_nls);
662 }
663
664 static void
665 db_insert_way_names_nls_cb(gpointer key, gpointer value, gpointer user_data)
666 {
667 way *w=(way *)user_data;
668
669 sqlite3_bind_int(sql.insert_way_names_nls, 1, w->id);
670 sqlite3_bind_text(sql.insert_way_names_nls, 2, (gchar *)key, -1, SQLITE_TRANSIENT);
671 sqlite3_bind_text(sql.insert_way_names_nls, 3, (gchar *)value, -1, SQLITE_TRANSIENT);
672
673 db_exec(sql.insert_way_names_nls);
674 }
675
676 static void
677 db_insert_way_names_nls(way *w)
678 {
679 if (!w->data)
680         return;
681 if (!w->data->names)
682         return;
683
684 g_hash_table_foreach(w->data->names, db_insert_way_names_nls_cb, w);
685 }
686
687 /**
688  * Insert all data for the given way
689  * - name
690  * - ref
691  * - nodes
692  * 
693  */
694 static gboolean
695 db_insert_way(way *w)
696 {
697 GSList *iter;
698
699 if (!w)
700         return FALSE;
701
702 /* Skip things we don't use (yet) */
703 if (w->type==WAY_UNWAYED || w->type>WAY_ROAD_END)
704         return TRUE;
705
706 /* Insert nodes */
707 for (iter=w->nodes; iter!=NULL; iter=iter->next) {
708         if (!iter->next)
709                 break;
710         db_insert_way_n2n(w, iter->data, iter->next->data);
711 }
712
713 if (w->id==0)
714         return FALSE;
715
716 if (w->data)
717         w->data->isin=osm_find_way_place(w);
718
719 print_way(w);
720
721 sqlite3_bind_int(sql.insert_way_data, 1, w->id);
722 sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt);
723 sqlite3_bind_int(sql.insert_way_data, 3, w->type);
724 sqlite3_bind_int(sql.insert_way_data, 4, w->flags);
725 if (w->data) {
726         sqlite3_bind_int(sql.insert_way_data, 5, w->data->speed);
727         sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin);
728 }
729
730 db_exec(sql.insert_way_data);
731
732 db_insert_way_ref(w);
733 db_insert_way_name(w);
734 db_insert_way_names_nls(w);
735
736 osm_free_way_data(w);
737 return TRUE;
738 }
739
740 /********************************************************************/
741
742 static gchar *
743 get_attr_key_value(const gchar **p, gchar *key)
744 {
745 gchar **d;
746
747 d=p;
748 while (*d!=NULL) {
749         if (strncmp(*d, key, strlen(key))==0) {
750                 d++;
751                 return *d;
752         }
753         d++;
754         d++;
755 }
756 return NULL;
757 }
758
759 static tag_state_t 
760 check_tag(const gchar *tag)
761 {
762 if (strcmp(tag,"node")==0) return IN_NODE_TAG;
763 else if (strcmp(tag,"nd")==0) return IN_WNODE_TAG;
764 else if (strcmp(tag,"way")==0) return IN_WAY_TAG;
765 else if (strcmp(tag,"tag")==0) return IN_KEY_TAG;
766 else if (strcmp(tag,"osm")==0) return IN_OSM_TAG;
767 else if (strcmp(tag,"bound")==0) return IN_BOUND_TAG;
768 else if (strcmp(tag,"relation")==0) return IN_RELATION_TAG;
769 else if (strcmp(tag,"member")==0) return IN_MEMBER_TAG;
770 else return ERROR;
771 }
772
773 static void
774 find_nls_names(gpointer key, gpointer value, gpointer user_data)
775 {
776 gchar *k, *v;
777 gchar *tmp;
778 GHashTable *nls;
779
780 k=(gchar *)key;
781 v=(gchar *)value;
782 nls=(GHashTable *)user_data;
783
784 /* Check if it is a name key, return if not. */
785 if (g_str_has_prefix(k, "name:")==FALSE)
786         return;
787
788 tmp=g_strrstr(k, ":");
789 if (!tmp)
790         return;
791 tmp++; /* skip : */
792 if (*tmp==0)
793         return;
794 g_hash_table_insert(nls, g_strdup(tmp), g_strdup(v));
795 #ifdef VERBOSE
796 g_printf("NLS(%s): [%s]\n", tmp, v);
797 #endif
798 }
799
800 /********************************************************************/
801
802 static void
803 node_print (node *n)
804 {
805 g_assert(n);
806 if (n->data) {
807         g_printf("N: %d [%f:%f][%s](%d)\n", 
808                 n->id, n->lat, n->lon, 
809                 n->data->name ? n->data->name : "-", 
810                 n->type);
811 } else {
812         g_printf("N: %d [%f:%f]\n",
813                 n->id, n->lat, n->lon);
814 }
815 }
816
817 #ifdef DEBUG
818 static void 
819 dump_array(const gchar **p)
820 {
821 char **d;
822
823 d=p;
824 while (*d!=NULL) {
825         g_printf("[%s]", *d);
826         d++;
827 }
828 g_print("\n");
829 }
830 #endif
831
832 static gboolean
833 osm_node_check_box(gdouble nlat, gdouble nlon)
834 {
835 if (use_bbox==FALSE)
836         return TRUE;
837 return (nlat > bbox.lat_min && nlat < bbox.lat_max && nlon > bbox.lon_min && nlon < bbox.lon_max) ? TRUE : FALSE;
838 }
839
840 static void
841 osm_new_node_data(node *n)
842 {
843 if (n==NULL) return;
844 if (n->data!=NULL) return;
845 n->data=g_slice_new(node_data);
846 n->data->name=NULL;
847 n->type=NODE_PLAIN;
848 noded_cnt++;
849 }
850
851 static void
852 osm_free_node_data(node *n)
853 {
854 g_assert(n);
855 g_assert(n->data);
856 if (n->data->name)
857         g_free(n->data->name);
858 g_slice_free(node_data, n->data);
859 n->data=NULL;
860 noded_cnt--;
861 }
862
863 static node *
864 osm_new_node(gint id, gdouble lat, gdouble lon)
865 {
866 node *n=NULL;
867
868 n=g_slice_new(node);
869 g_assert(n);
870 n->id=id;
871 n->lat=lat;
872 n->lon=lon;
873 n->data=(node_data *)NULL;
874 g_hash_table_insert(osm_nodes, GINT_TO_POINTER(id), n);
875 return n;
876 }
877
878 static node *
879 osm_find_node(guint32 nid)
880 {
881 node *n;
882 n=g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
883 #if 0
884 if (!n)
885         g_printerr("ERROR: Node %d not found!\n", nid);
886 #endif
887 return n;
888 }
889
890 static void
891 osm_new_way_data(way *w)
892 {
893 if (w==NULL) return;
894 if (w->data!=NULL) return;
895
896 w->data=g_slice_new(way_data);
897 w->data->name=NULL;
898 w->data->names=NULL;
899 w->data->ref=NULL;
900 w->data->int_ref=NULL;
901 w->data->layer=0;
902 w->data->speed=0;
903 }
904
905 static void
906 osm_free_way_data(way *w)
907 {
908 if (!w->data)
909         return;
910 if (w->data->name)
911         g_free(w->data->name);
912 if (w->data->ref)
913         g_free(w->data->ref);
914 if (w->data->int_ref)
915         g_free(w->data->int_ref);
916 g_slice_free(way_data, w->data);
917 w->data=NULL;
918 }
919
920 static way *
921 osm_new_way(gint id)
922 {
923 way *w;
924
925 w=g_slice_new(way);
926 w->id=id;
927 w->nodes=NULL;
928 w->type=WAY_UNWAYED;
929 w->data=NULL;
930 w->ncnt=0;
931 w->flags=0;
932
933 /* Add to list of ways */
934 return w;
935 }
936
937 static void
938 osm_way_add_to_list(way *w)
939 {
940 osm_ways=g_slist_prepend(osm_ways, w);
941 }
942
943 static void
944 osm_way_new_node(way *w, gint nid)
945 {
946 node *n;
947
948 n=osm_find_node(nid);
949 w->nodes=g_slist_prepend(w->nodes, n);
950 w->ncnt++;
951 }
952
953 /**
954  * Search the place hash table for the location of the node.
955  *
956  */
957 static guint32 
958 osm_find_node_place(node *n)
959 {
960 node *t;
961 gchar **isin;
962 gchar **place;
963
964 if (!n->data)
965         return 0;
966
967 isin=g_hash_table_lookup(osm_node_isin, GINT_TO_POINTER(n->id));
968
969 if (!isin)
970         return 0;
971
972 place=isin;
973 while (*place!=NULL) {
974         gchar *ps;
975         ps=g_strstrip(*place);
976 #ifdef VERBOSE
977         g_printf("Checking (%d) [%s] in [%s]\n",n->type, n->data->name, ps);
978 #endif
979         switch (n->type) {
980         case NODE_PLACE_CITY:
981         case NODE_PLACE_TOWN:
982         case NODE_PLACE_VILLAGE:
983         case NODE_PLACE_HAMLET:
984                 t=g_hash_table_lookup(osm_place_region, ps);
985                 if (t)
986                         return t->id;
987                 t=g_hash_table_lookup(osm_place_country, ps);
988                 if (t)
989                         return t->id;
990         break;
991         case NODE_PLACE_SUBURB:
992                 t=g_hash_table_lookup(osm_place_city, ps);
993                 if (t)
994                         return t->id;
995         break;
996         case NODE_PLACE_ISLAND:
997                 return 0;
998         break;
999         default:
1000                 t=g_hash_table_lookup(osm_place_city, ps);
1001                 if (t)
1002                         return t->id;
1003         break;
1004         }
1005         place++;
1006 }
1007
1008 return 0;
1009 }
1010
1011 guint32
1012 osm_find_way_place(way *w)
1013 {
1014 gchar **isin;
1015 gchar **place;
1016
1017 isin=g_hash_table_lookup(osm_way_isin, GINT_TO_POINTER(w->id));
1018 if (!isin)
1019         return 0;
1020
1021 place=isin;
1022 while (*place!=NULL) {
1023         node *t;
1024         gchar *ps;
1025
1026         ps=g_strstrip(*place);
1027
1028 #ifdef VERBOSE
1029         g_printf("Checking (%d) in [%s]\n",w->id, ps);
1030 #endif
1031
1032         t=g_hash_table_lookup(osm_place_city, ps);
1033         if (t)
1034                 return t->id;
1035         place++;
1036 }
1037
1038 return 0;
1039 }
1040
1041 /***********************************************************************/
1042
1043 static void
1044 osm_node_save_node(gint key, gpointer value, gpointer user_data)
1045 {
1046 node *n=(node *)value;
1047
1048 dbnode_cnt++;
1049 db_insert_node(n);
1050 if (dbnode_cnt % 26214==0)
1051                 g_printf("Nodes: %f%%\n",((float)dbnode_cnt/(float)node_cnt)*100);
1052 }
1053
1054 /**
1055  * Check node type and insert as POI or Place
1056  * Discard extra data after insert.
1057  */
1058 static gboolean
1059 osm_node_save_poi(node *n, gpointer user_data)
1060 {
1061 if (!n) {
1062         g_printerr("ERROR: null poi\n");
1063         return FALSE;
1064 }
1065
1066 if (!n->data) {
1067         g_printerr("POI node with no data ?\n");
1068         return FALSE;
1069 }
1070
1071 n->data->isin=osm_find_node_place(n);
1072
1073 if (n->type>NODE_POI_START && n->type<NODE_POI_END) {
1074         print_node(n);
1075         db_insert_poi(n);
1076 } else if (n->type>NODE_PLACE_START && n->type<NODE_PLACE_END) {
1077         print_node(n);
1078         db_insert_place(n);
1079 } else {
1080         osm_free_node_data(n);
1081         return FALSE;
1082 }
1083
1084 /* Free the extra info, we don't need it anymore */
1085 #if 0
1086 osm_free_node_data(n);
1087 #endif
1088 return TRUE;
1089 }
1090
1091 static void
1092 osm_planet_poi_clear_nodes(void)
1093 {
1094 g_print("Removing old OSM POIs...\n");
1095 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1096 sqlite3_step(sql.delete_osm_poi);
1097 sqlite3_step(sql.delete_place);
1098 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1099 }
1100
1101 static void
1102 osm_planet_poi_save_nodes(void)
1103 {
1104 g_print("Storing new POIs...\n");
1105 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1106 g_slist_foreach(osm_poi, osm_node_save_poi, NULL);
1107 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1108 g_slist_free(osm_poi);
1109 }
1110
1111 /*********************************************************************/
1112
1113 static void
1114 osm_planet_clear_nodes(void)
1115 {
1116 g_print("Clearing old nodes\n");
1117 sqlite3_step(sql.delete_nodes);
1118 }
1119
1120 static void
1121 osm_planet_save_nodes(void)
1122 {
1123 g_print("Storing nodes...\n");
1124
1125 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1126 g_hash_table_foreach(osm_nodes, osm_node_save_node, NULL);
1127 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1128 }
1129
1130 /*********************************************************************/
1131
1132 static void
1133 osm_way_save(way *value, gpointer user_data)
1134 {
1135 dbway_cnt++;
1136 db_insert_way(value);
1137 if (dbway_cnt % 8192==0 && dbway_cnt>0) {
1138                 g_printf("Ways: %f%%\n",(((float)dbway_cnt/(float)way_cnt)*100));
1139                 print_way(value);
1140 }
1141 }
1142
1143 static void
1144 osm_planet_clear_ways(void)
1145 {
1146 g_print("Clearing old data:\n");
1147 sqlite3_step(sql.delete_way);
1148 sqlite3_step(sql.delete_way_name);
1149 sqlite3_step(sql.delete_way_ref);
1150 sqlite3_step(sql.delete_way_n2n);
1151 }
1152
1153 static void
1154 osm_planet_save_ways(void)
1155 {
1156 g_print("Inserting new ways:\n");
1157 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1158 g_slist_foreach(osm_ways, osm_way_save, NULL);
1159 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1160 }
1161
1162 /*********************************************************************/
1163
1164 static void
1165 osm_planet_save_all_nodes(void)
1166 {
1167 g_printf("Saving planet nodes to database:\n");
1168
1169 osm_planet_poi_clear_nodes();
1170 osm_planet_poi_save_nodes();
1171
1172 if (!is_update) {
1173         osm_planet_clear_nodes();
1174         osm_planet_clear_ways();
1175 }
1176 osm_planet_save_nodes();
1177 }
1178
1179 static void
1180 osm_planet_save_all_ways(void)
1181 {
1182 g_printf("Saving planet way to database:\n");
1183
1184 osm_planet_save_ways();
1185 }
1186
1187 /***********************************************************************/
1188
1189 static void
1190 _osm_tag_start(void *userData, const char *name, const char **atts)
1191 {
1192 tag_state_t t;
1193 gchar *k, *v;
1194 guint32 id, ndref;
1195 gdouble nlat, nlon;
1196
1197 t=check_tag(name);
1198 switch (t) {
1199         case IN_OSM_TAG:
1200                 g_printf("Starting...\n");
1201         break;
1202         case IN_NODE_TAG:
1203                 tag_parent=IS_NODE;
1204                 node_cnt++;
1205
1206                 id=atoi(get_attr_key_value(atts, "id"));
1207                 nlat=atof(get_attr_key_value(atts, "lat"));
1208                 nlon=atof(get_attr_key_value(atts, "lon"));
1209
1210                 /* Check if node is used */
1211                 if (osm_node_check_box(nlat, nlon)==TRUE) {
1212                         cnode=osm_new_node(id, nlat, nlon);
1213                         osm_node_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1214                 } else {
1215                         osm_node_tags=NULL;
1216                         node_skip_cnt++;
1217                 }
1218         break;
1219         case IN_WAY_TAG:
1220                 tag_parent=IS_WAY;
1221                 way_cnt++;
1222                 id=atoi(get_attr_key_value(atts, "id"));
1223                 cway=osm_new_way(id);
1224                 osm_way_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1225         break;
1226         case IN_WNODE_TAG:
1227                 ndref=atoi(get_attr_key_value(atts, "ref"));
1228                 if (use_bbox==TRUE) {
1229                         if (osm_find_node(ndref)==NULL) {
1230                                 cway->id=0;
1231                                 return;
1232                         }
1233                 }
1234                 osm_way_new_node(cway, ndref);
1235         break;
1236         case IN_KEY_TAG:
1237                 k=get_attr_key_value(atts, "k");
1238                 if (strcmp(k,"created_by")==0)
1239                         return;
1240                 if (strcmp(k,"source")==0)
1241                         return;
1242
1243                 v=get_attr_key_value(atts, "v");
1244 #ifdef VERBOSE_KEYS
1245                 g_printf("TAG: K=[%s] V=[%s]\n", k, v);
1246 #endif
1247
1248                 switch (tag_parent) {
1249                 case IS_NONE:
1250                         g_printf("Tag key/value pair but unknown owner\n");
1251                 break;
1252                 case IS_NODE:
1253                 {
1254                         if (!osm_node_tags)
1255                                 return;
1256
1257                         /* Insert key/value pairs into hash table */
1258                         if (cnode==NULL) {
1259                                 g_printerr("In node tags but node is NULL!\n");
1260                                 return;
1261                         }
1262                         g_hash_table_insert(osm_node_tags, g_strdup(k), g_strdup(v));
1263                 }
1264                 break;
1265                 case IS_WAY: 
1266                 {
1267                         if (cway==NULL) {
1268                                 g_printerr("In way tags but way is NULL!\n");
1269                                 return;
1270                         }
1271                         g_hash_table_insert(osm_way_tags, g_strdup(k), g_strdup(v));
1272                         osm_new_way_data(cway);
1273                 }
1274                 break;
1275                 case IS_RELATION:
1276
1277                 break;
1278                 }
1279         break;
1280         case IN_BOUND_TAG:
1281                 /* Ignore for now */
1282                 g_printf("Ignoring bound tag\n");
1283         break;
1284         case IN_RELATION_TAG:
1285                 tag_parent=IS_RELATION;
1286
1287         break;
1288         case IN_MEMBER_TAG:
1289
1290         break;
1291         default:
1292                 tag_parent=IS_NONE;
1293                 g_printf("Unknown tag: %s\n", name);
1294         break;
1295 }
1296 }
1297
1298 static void
1299 _osm_tag_end(void *userData, const char *name)
1300 {
1301 tag_state_t t;
1302 gchar *v;
1303 guint i;
1304 t=check_tag(name);
1305 switch (t) {
1306         case IN_NODE_TAG:
1307                 if (node_cnt % 262140==0) {
1308                         g_printf("Nodes: %d of %d, POIs: %d, Outside box: %d\n", node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
1309                 }
1310
1311                 if (!osm_node_tags)
1312                         return;
1313
1314                 osm_new_node_data(cnode);
1315
1316                 for (i=0; nodeinfo[i].k; i++) {
1317                         v=g_hash_table_lookup(osm_node_tags, nodeinfo[i].k);
1318                         if (!v)
1319                                 continue;
1320                         if (strcasecmp (v, nodeinfo[i].v)==0) {
1321                                 cnode->type=nodeinfo[i].type;
1322                                 break;
1323                         }
1324                 }
1325
1326                 if (cnode->type!=NODE_PLAIN) {
1327                         cnode->data->name=NULL;
1328                         v=g_hash_table_lookup(osm_node_tags, "name");
1329                         if (v)
1330                                 cnode->data->name=g_strstrip(g_strdup(v));
1331                 }
1332
1333                 cnode->data->isin=0;
1334                 v=g_hash_table_lookup(osm_node_tags, "is_in");
1335                 if (v) {
1336                         gchar **isin;                           
1337                         isin=g_strsplit(v, ",", 10);
1338                         g_hash_table_insert(osm_node_isin, GINT_TO_POINTER(cnode->id), isin);
1339                 }
1340
1341                 if (cnode->type==NODE_PLAIN) {
1342                         osm_free_node_data(cnode);
1343                 } else {
1344                         osm_poi=g_slist_prepend(osm_poi, cnode);
1345                         if (cnode->data->name) {
1346                                 switch (cnode->type) {
1347                                 case NODE_PLACE_COUNTRY:
1348                                         g_printf("Country: [%s] (%d)\n", cnode->data->name, cnode->id);
1349                                         g_hash_table_insert(osm_place_country, cnode->data->name, cnode);
1350                                 break;
1351                                 case NODE_PLACE_CITY:
1352                                 case NODE_PLACE_TOWN:
1353                                         g_printf("City: [%s] (%d)\n", cnode->data->name, cnode->id);
1354                                         g_hash_table_insert(osm_place_city, cnode->data->name, cnode);
1355                                 break;
1356                                 case NODE_PLACE_SUBURB:
1357                                         g_hash_table_insert(osm_place_suburb, cnode->data->name, cnode);
1358                                 break;
1359                                 case NODE_PLACE_VILLAGE:
1360                                 case NODE_PLACE_HAMLET:
1361                                         g_hash_table_insert(osm_place_village, cnode->data->name, cnode);
1362                                 break;
1363                                 case NODE_PLACE_ISLAND:
1364                                         /* Ignore for now */
1365                                 break;
1366                                 default:;
1367                                 }
1368                         }
1369                 }
1370                 g_hash_table_destroy(osm_node_tags);
1371                 cnode=NULL;
1372         break;
1373         case IN_WAY_TAG:
1374                 if (way_cnt % 1024==0) {
1375                         g_printf("Ways: %d\n", way_cnt);
1376                 }
1377
1378                 cway->nodes=g_slist_reverse(cway->nodes);
1379
1380                 for (i=0; wayinfo[i].k; i++) {
1381                         v=g_hash_table_lookup(osm_way_tags, wayinfo[i].k);
1382                         if (!v)
1383                                 continue;
1384                         if (strcasecmp (v, wayinfo[i].v)==0) {
1385                                 if (wayinfo[i].link==TRUE)
1386                                         cway->flags|=W_LINK;
1387                                 if (wayinfo[i].area==TRUE)
1388                                         cway->flags|=W_AREA;
1389                                 if (wayinfo[i].oneway==TRUE)
1390                                         cway->flags|=W_ONEWAY;
1391                                 cway->type=wayinfo[i].type;
1392                                 if (cway->data->speed==0)
1393                                         cway->data->speed=wayinfo[i].defspeed;
1394                                 break;
1395                         }
1396                 }
1397
1398                 v=g_hash_table_lookup(osm_way_tags, "name");
1399                 if (v) {
1400                         cway->data->name=g_strdup(v);
1401                         /* Try to find other language names */
1402                         cway->data->names=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1403                         g_hash_table_foreach(osm_way_tags, find_nls_names, cway->data->names);
1404                         if (g_hash_table_size(cway->data->names)==0) {
1405                                 g_hash_table_destroy(cway->data->names);
1406                                 cway->data->names=NULL;
1407                         }
1408                 }
1409
1410                 v=g_hash_table_lookup(osm_way_tags, "ref");
1411                 if (v)
1412                         cway->data->ref=g_strdup(v);
1413                 v=g_hash_table_lookup(osm_way_tags, "int_ref");
1414                 if (v)
1415                         cway->data->int_ref=g_strdup(v);
1416
1417                 v=g_hash_table_lookup(osm_way_tags, "oneway");
1418                 if (v)
1419                         cway->flags|=W_ONEWAY;
1420                 v=g_hash_table_lookup(osm_way_tags, "noexit");
1421                 if (v)
1422                         cway->flags|=W_NOEXIT;
1423                 
1424                 v=g_hash_table_lookup(osm_way_tags, "speedlimit");
1425                 if (v)
1426                         cway->data->speed=atoi(v);
1427                 v=g_hash_table_lookup(osm_way_tags, "maxspeed");
1428                 if (v)
1429                         cway->data->speed=atoi(v);
1430
1431 #if 0
1432                 v=g_hash_table_lookup(osm_way_tags, "layer");
1433                 if (v)
1434                         cway->data->layer=atoi(v);
1435 #endif
1436
1437                 v=g_hash_table_lookup(osm_way_tags, "junction");
1438                 if (v && strcasecmp(v,"roundabout")==0) {
1439                         cway->flags|=W_ROUNDABOUT;
1440                         cway->flags|=W_ONEWAY;
1441                 } else if (v && strcasecmp(v,"mini_roundabout")==0) {
1442                         cway->flags|=W_ROUNDABOUT;
1443                         cway->flags|=W_ONEWAY;
1444                 }
1445
1446                 /* XXX: Should check keys */
1447                 v=g_hash_table_lookup(osm_way_tags, "access");
1448                 if (v && (strcasecmp(v, "private")==0)) {
1449                         cway->flags|=W_NOACCESS;
1450                 }
1451
1452                 print_way(cway);
1453
1454                 v=g_hash_table_lookup(osm_way_tags, "is_in");
1455                 if (v) {
1456                         gchar **isin;                           
1457                         isin=g_strsplit(v, ",", 10);
1458                         g_hash_table_insert(osm_way_isin, GINT_TO_POINTER(cway->id), isin);
1459                 }
1460
1461                 if (cway->data && cway->data->name==NULL && cway->data->ref==NULL &&
1462                         cway->data->int_ref==NULL && cway->data->layer==0 && cway->data->speed==0)
1463                         osm_free_way_data(cway);
1464
1465                 if (cway->id!=0)
1466                         osm_way_add_to_list(cway);
1467
1468                 cway=NULL;
1469                 g_hash_table_destroy(osm_way_tags);
1470         break;
1471         case IN_BOUND_TAG:
1472                 /* */
1473         break;
1474         case IN_OSM_TAG:
1475                 g_printf("Planet loaded.\n");
1476         break;
1477         default:;
1478 }
1479 }
1480
1481 /************************************************************************/
1482
1483 static void
1484 storage_init(void)
1485 {
1486 osm_nodes=g_hash_table_new(g_direct_hash, g_direct_equal);
1487
1488 osm_place_country=g_hash_table_new(g_str_hash, g_str_equal);
1489 osm_place_city=g_hash_table_new(g_str_hash, g_str_equal);
1490 osm_place_suburb=g_hash_table_new(g_str_hash, g_str_equal);
1491 osm_place_village=g_hash_table_new(g_str_hash, g_str_equal);
1492 osm_place_region=g_hash_table_new(g_str_hash, g_str_equal);
1493 osm_node_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
1494 osm_way_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
1495 }
1496
1497 static void
1498 storage_free(void)
1499 {
1500 g_hash_table_destroy(osm_nodes);
1501
1502 g_hash_table_destroy(osm_place_country);
1503 g_hash_table_destroy(osm_place_city);
1504 g_hash_table_destroy(osm_place_suburb);
1505 g_hash_table_destroy(osm_place_village);
1506 g_hash_table_destroy(osm_place_region);
1507 g_hash_table_destroy(osm_node_isin);
1508 }
1509
1510 void
1511 osm_planet_parser_init(void)
1512 {
1513 xp=XML_ParserCreate(NULL);
1514 XML_SetElementHandler(xp, _osm_tag_start, _osm_tag_end);
1515 storage_init();
1516 }
1517
1518 void
1519 osm_planet_parser_deinit(void)
1520 {
1521 XML_ParserFree(xp);
1522 storage_free();
1523 }
1524
1525 gboolean
1526 osm_planet_parse_buffer(gchar *buffer, size_t r)
1527 {
1528 if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) {
1529         g_printerr("Parse error at line %d:\n%s\n",
1530         XML_GetCurrentLineNumber(xp),
1531         XML_ErrorString(XML_GetErrorCode(xp)));
1532         return FALSE;
1533 }
1534 return TRUE;
1535 }
1536
1537 gboolean 
1538 osm_planet_parse_file(gchar *pfile)
1539 {
1540 FILE *f;
1541 BZFILE *b;
1542 int bzerror;
1543 int r;
1544 gchar buffer[FILE_BUFFER];
1545 gboolean res=TRUE;
1546
1547 f=fopen(pfile, "r");
1548 if (!f) 
1549         return FALSE;
1550
1551 b=BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
1552 if (bzerror != BZ_OK) {
1553         BZ2_bzReadClose(&bzerror, b);
1554         return FALSE;
1555 }
1556
1557 do {
1558         r=BZ2_bzRead(&bzerror, b, buffer, FILE_BUFFER);
1559         if ((bzerror!=BZ_STREAM_END) && (bzerror!=BZ_OK)) {
1560                 res=FALSE;
1561                 break;
1562         }
1563         if (!osm_planet_parse_buffer(buffer, r)) {
1564                 res=FALSE;
1565                 break;
1566         }
1567 } while (bzerror==BZ_OK);
1568
1569 BZ2_bzReadClose(&bzerror, b);
1570 fclose(f);
1571 return res;
1572 }
1573
1574 /************************************************************************/
1575
1576 static gint
1577 print_fail(const gchar *msg, gint ret)
1578 {
1579 g_printerr("ERROR: %s\n", msg);
1580 return ret;
1581 }
1582
1583 /************************************************************************/
1584
1585 static void
1586 print_memory_usage(void)
1587 {
1588 g_print("Memory usage per item:\n");
1589 g_printf("Node  size: %d\n", (int)sizeof(node));
1590 g_printf("NodeD size: %d\n", (int)sizeof(node_data));
1591 g_printf("Way   size: %d\n", (int)sizeof(way));
1592 g_printf("WayD  size: %d\n", (int)sizeof(way_data));
1593 }
1594
1595 /************************************************************************/
1596
1597 int main (int argc, char **argv)
1598 {
1599 if (argc<2) {
1600         return print_fail("Give bzip2 compressed planet XML file as argument", 1);
1601 } else {
1602         g_printf("Using file: %s\n", argv[1]);
1603 }
1604
1605 if (argc==6) {
1606         use_bbox=TRUE;
1607         bbox.lat_min=atof(argv[2]);
1608         bbox.lon_min=atof(argv[3]);
1609         bbox.lat_max=atof(argv[4]);
1610         bbox.lon_max=atof(argv[5]);
1611         g_printf("Skipping data outside of box: %f,%f - %f,%f\n",
1612                 bbox.lat_min, bbox.lon_min,
1613                 bbox.lat_max, bbox.lon_max);
1614         g_print("Note: missing nodes can't be reported.\n");
1615 } else use_bbox=FALSE;
1616
1617 if (db_connect(&db, OSM_DB_FILE)!=TRUE)
1618         return print_fail("Database open failed", 2);
1619 db_prepare();
1620
1621 print_memory_usage();
1622
1623 osm_planet_parser_init();
1624 if (osm_planet_parse_file(argv[1])==FALSE)
1625         return 1;
1626
1627 g_printf("Total nodes %d, POIs: %d and Ways %d.\n",     node_cnt, noded_cnt, way_cnt);
1628 g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
1629 g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
1630 g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
1631
1632 osm_planet_save_all_nodes();
1633 osm_planet_save_all_ways();
1634 osm_planet_parser_deinit();
1635 db_close(&db);
1636
1637 g_printf("Named ways: %d, Numbered ways: %d\n", way_names, way_refs);
1638
1639 return 0;
1640 }