# audio-note.c
osm2db_CFLAGS = $(EXPAT_CFLAGS) $(SQLITE_CFLAGS) $(GLIBGTK_CFLAGS)
-osm2db_LDADD = $(EXPAT_LIBS) $(SQLITE_LIBS) $(GLIBGTK_LIBS) $(BZ2_LIBS) -lm libosmdb.la
+osm2db_LDADD = $(EXPAT_LIBS) $(SQLITE_LIBS) $(GLIBGTK_LIBS) -lm libosmdb.la
osm2db_SOURCES = osm.c
lib_LTLIBRARIES = libgtkgps.la libosmdb.la libmappergps.la
libgtkgps_la_LIBADD = $(GLIBGTK_LIBS)
libgtkgps_la_LDFLAGS = -lm -no-undefined
-libosmdb_la_SOURCES = db.c osm-db.c latlon.c
+libosmdb_la_SOURCES = db.c osm-db.c osm-db-import.c latlon.c
libosmdb_la_CFLAGS = $(GLIBGTK_CFLAGS) $(SQLITE_CFLAGS) $(defines)
-libosmdb_la_LIBADD = $(GLIBGTK_LIBS) $(SQLITE_LIBS)
+libosmdb_la_LIBADD = $(GLIBGTK_LIBS) $(SQLITE_LIBS) $(BZ2_LIBS)
libosmdb_la_LDFLAGS = -lm -no-undefined
EXTRA_DIST = gps-bluetooth-maemo-marshal.list gps-bluetooth-bluez-marshal.list
--- /dev/null
+/*
+ * This file is part of mapper
+ *
+ * Copyright (C) 2007 Kaj-Michael Lang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Routines to read OSM planet XML file and store it in a sqlite3 database.
+ * Reads in all nodes (if used, skips nodes outside bounding box)
+ * Special POI nodes are stored in POI table.
+ * Place POI nodes are stored in place table.
+ *
+ * Ways are read in and their data (name, type, etc) are stored
+ * in way, way_name and way_ref tables.
+ *
+ * Nodes used by they ways are stored in way_n2n table.
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <math.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <sqlite3.h>
+#include <expat.h>
+#include <bzlib.h>
+
+#include "osm.h"
+#include "latlon.h"
+#include "db.h"
+#include "osm-db-import.h"
+
+#if 0
+#define VERBOSE
+#endif
+/* #define VERBOSE_KEYS */
+
+
+/* Use g_convert to transliterate names.. my iconv seems to be fucked so this didn't work... */
+/* #define TRANSLIT_NAMES */
+
+#define FILE_BUFFER 65535
+
+static guint node_cnt=0;
+static guint node_skip_cnt=0;
+static guint noded_cnt=0;
+static guint way_cnt=0;
+static guint way_names=0;
+static guint way_refs=0;
+
+static guint dbnode_cnt=0;
+static guint dbnoded_cnt=0;
+static guint dbway_cnt=0;
+
+static gboolean is_update=FALSE;
+static XML_Parser xp;
+
+
+/* XML tag IDs */
+typedef enum {
+ START,
+ IN_OSM_TAG,
+ IN_NODE_TAG,
+ IN_WNODE_TAG,
+ IN_WAY_TAG,
+ IN_KEY_TAG,
+ IN_BOUND_TAG,
+ IN_RELATION_TAG,
+ IN_MEMBER_TAG,
+ END,
+ ERROR
+} tag_state_t;
+
+/* Parent tag type */
+typedef enum {
+ IS_NONE,
+ IS_NODE,
+ IS_WAY,
+ IS_RELATION
+} tag_parent_t;
+
+/* Node types table */
+/* XXX: Add support for parent category */
+struct _nodeinfo {
+ gchar *k, *v;
+ node_type_t type;
+} nodeinfo[] = {
+ { "amenity", "fuel", NODE_AMENITY_FUEL },
+ { "amenity", "parking", NODE_AMENITY_PARKING },
+
+ { "amenity", "pub", NODE_AMENITY_PUB },
+ { "amenity", "nightclub", NODE_AMENITY_NIGHTCLUB },
+ { "amenity", "biergarten", NODE_AMENITY_PUB },
+ { "amenity", "cafe", NODE_AMENITY_CAFE },
+ { "amenity", "fast_food", NODE_AMENITY_FOOD },
+ { "amenity", "restaurant", NODE_AMENITY_FOOD },
+
+ { "amenity", "telephone", NODE_AMENITY_TELEPHONE },
+ { "amenity", "toilets", NODE_AMENITY_WC },
+
+ { "amenity", "hospital", NODE_AMENITY_HOSPITAL },
+ { "amenity", "doctors", NODE_AMENITY_HOSPITAL },
+ { "amenity", "pharmacy", NODE_AMENITY_PHARMACY },
+
+ { "amenity", "post_office", NODE_AMENITY_POST },
+ { "amenity", "post_box", NODE_AMENITY_POST_BOX },
+
+ { "amenity", "cinema", NODE_AMENITY_CINEMA },
+ { "amenity", "theatre", NODE_AMENITY_THEATRE },
+
+ { "amenity", "atm", NODE_AMENITY_ATM },
+ { "amenity", "bank", NODE_AMENITY_BANK },
+
+ { "amenity", "police", NODE_AMENITY_POLICE },
+ { "amenity", "speed_trap", NODE_AMENITY_SPEEDCAM },
+ { "amenity", "speed_camera", NODE_AMENITY_SPEEDCAM },
+ { "amenity", "speed camera", NODE_AMENITY_SPEEDCAM },
+
+ { "amenity", "place_of_worship",NODE_AMENITY_POW },
+
+ { "amenity", "school", NODE_AMENITY_SCHOOL },
+ { "amenity", "college", NODE_AMENITY_COLLEGE },
+ { "amenity", "university", NODE_AMENITY_COLLEGE },
+
+ { "amenity", "library", NODE_AMENITY_LIBRARY },
+ { "amenity", "townhall", NODE_AMENITY_TOWNHALL },
+
+ { "amenity", "supermarket", NODE_AMENITY_SHOP },
+ { "amenity", "shopping_centre", NODE_AMENITY_SHOP },
+ { "amenity", "shop", NODE_AMENITY_SHOP },
+ { "amenity", "shops", NODE_AMENITY_SHOP },
+ { "amenity", "shopping", NODE_AMENITY_SHOP },
+ { "amenity", "shopping_mall",NODE_AMENITY_SHOP },
+ { "amenity", "cycle_shop", NODE_AMENITY_SHOP },
+ { "amenity", "bike_shop", NODE_AMENITY_SHOP },
+ { "amenity", "coffee_shop", NODE_AMENITY_SHOP },
+ { "amenity", "indoor_shopping_centre", NODE_AMENITY_SHOP },
+ { "amenity", "farm_shop", NODE_AMENITY_SHOP },
+ { "amenity", "tea_shop", NODE_AMENITY_SHOP },
+
+ /* Shops */
+ { "shop", "supermarket", NODE_AMENITY_SHOP },
+ { "shop", "bakery", NODE_AMENITY_SHOP },
+ { "shop", "alcohol", NODE_AMENITY_SHOP },
+ { "shop", "butcher", NODE_AMENITY_SHOP },
+ { "shop", "flowers", NODE_AMENITY_SHOP },
+ { "shop", "clothing", NODE_AMENITY_SHOP },
+ { "shop", "souvenir", NODE_AMENITY_SHOP },
+ { "shop", "bicycles", NODE_AMENITY_SHOP },
+ { "shop", "grocers", NODE_AMENITY_SHOP },
+ { "shop", "newsagents", NODE_AMENITY_SHOP },
+ { "shop", "convenience", NODE_AMENITY_SHOP },
+ { "shop", "bakers", NODE_AMENITY_SHOP },
+ { "shop", "garden_centre",NODE_AMENITY_SHOP },
+ { "shop", "photography", NODE_AMENITY_SHOP },
+ { "shop", "general_store",NODE_AMENITY_SHOP },
+ { "shop", "food", NODE_AMENITY_SHOP },
+ { "shop", "drinks", NODE_AMENITY_SHOP },
+ { "shop", "pharmacy", NODE_AMENITY_PHARMACY },
+
+ /* Sport */
+ { "sport" , "swimming", NODE_SPORT_SWIMMING },
+ { "sport" , "golf", NODE_SPORT_GOLF },
+ { "sport" , "tennis", NODE_SPORT_TENNIS },
+ { "sport" , "football", NODE_SPORT_FOOTBALL },
+ { "sport" , "soccer", NODE_SPORT_SOCCER },
+ { "sport" , "baskteball", NODE_SPORT_BASKETBALL },
+ { "sport" , "rugby", NODE_SPORT_RUGBY },
+ { "sport" , "skating", NODE_SPORT_SKATING },
+ { "sport" , "hockey", NODE_SPORT_HOCKEY },
+ { "sport" , "skateboard", NODE_SPORT_SKATEBOARD },
+ { "sport" , "bowling", NODE_SPORT_BOWLING },
+ { "sport" , "10pin", NODE_SPORT_BOWLING },
+ { "sport" , "motor", NODE_SPORT_MOTOR },
+ { "sport" , "shooting_range",NODE_SPORT_SHOOTING },
+ { "sport" , "paintball", NODE_SPORT_PAINTBALL },
+ { "sport" , "horse_racing",NODE_SPORT_HORSES },
+ { "sport" , "horse", NODE_SPORT_HORSES },
+ { "sport" , "horses", NODE_SPORT_HORSES },
+ { "sport" , "dog_racing", NODE_SPORT_DOG },
+ { "sport" , "pelota", NODE_SPORT_PELOTA },
+ { "sport" , "racquet", NODE_SPORT_RACQUET },
+ { "sport" , "equestrian", NODE_SPORT_HORSES },
+ { "sport" , "baseball", NODE_SPORT_BASEBALL },
+ { "sport" , "cricket", NODE_SPORT_CRICKET },
+ { "sport" , "croquet", NODE_SPORT_CROQUET },
+ { "sport" , "cycling", NODE_SPORT_CYCLING },
+ { "sport" , "bowls", NODE_SPORT_BOWLS },
+ { "sport" , "athletics", NODE_SPORT_ATHLETICS },
+ { "sport" , "gymnastics", NODE_SPORT_GYMNASTICS },
+ { "sport" , "multi", NODE_SPORT_OTHER },
+ { "leisure", "sport_centre",NODE_SPORT_CENTER },
+
+ /* Tourism */
+ { "tourism", "information", NODE_TOURISM_INFO },
+ { "tourism", "camp_site", NODE_TOURISM_CAMP_SITE },
+ { "tourism", "caravan_site",NODE_TOURISM_CARAVAN_SITE },
+ { "tourism", "picnic_site", NODE_TOURISM_PICNIC_SITE },
+ { "tourism", "theme_park", NODE_TOURISM_THEME_PARK },
+ { "tourism", "hotel", NODE_TOURISM_HOTEL },
+ { "tourism", "motel", NODE_TOURISM_MOTEL },
+ { "tourism", "hostel", NODE_TOURISM_HOSTEL },
+ { "tourism", "attraction", NODE_TOURISM_ATTRACTION },
+ { "tourism", "zoo", NODE_TOURISM_ATTRACTION },
+
+ { "historic", "ruins", NODE_TOURISM_ATTRACTION },
+ { "historic", "monument", NODE_TOURISM_ATTRACTION },
+ { "historic", "memorial", NODE_TOURISM_ATTRACTION },
+ { "historic", "museum", NODE_HISTORIC_MUSEUM },
+ { "historic", "castle", NODE_HISTORIC_CASTLE },
+
+ { "railway", "station", NODE_RAILWAY_STATION },
+ { "railway", "halt", NODE_RAILWAY_HALT },
+
+ { "aeroway", "terminal", NODE_AIRPORT_TERMINAL },
+
+ /* Places */
+ { "place", "city", NODE_PLACE_CITY },
+ { "place", "town", NODE_PLACE_TOWN },
+ { "place", "village", NODE_PLACE_VILLAGE },
+ { "place", "hamlet", NODE_PLACE_HAMLET },
+ { "place", "locality", NODE_PLACE_LOCALITY },
+ { "place", "suburb", NODE_PLACE_SUBURB },
+ { "place", "island", NODE_PLACE_ISLAND },
+
+ { "highway", "traffic_signals", NODE_TRAFFIC_SIGNALS },
+ { "highway", "motorway_junction", NODE_JUNCTION },
+ { "highway", "services", NODE_AMENITY_PARKING },
+ { "highway", "toll_booth", NODE_TOLLBOOTH },
+ { "highway", "gate", NODE_GATE },
+
+ { NULL, NULL, NODE_PLAIN }
+};
+
+/* Array to get id number and defaults for ways of different types */
+struct _wayinfo {
+ gchar *k, *v;
+ guint defspeed;
+ way_type_t type;
+ gboolean oneway, link, area, car, foot;
+} wayinfo[] = {
+ { "highway", "motorway",120,WAY_MOTORWAY, TRUE, FALSE, FALSE, TRUE, FALSE },
+ { "highway", "motorway_link",120,WAY_MOTORWAY, TRUE, TRUE, FALSE, TRUE, FALSE },
+ { "highway", "trunk",100,WAY_TRUNK, FALSE, FALSE, FALSE, TRUE, FALSE },
+ { "highway", "trunk_link",100,WAY_TRUNK, FALSE, TRUE, FALSE, TRUE, FALSE },
+ { "highway", "primary",80,WAY_PRIMARY, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "primary_link",60,WAY_PRIMARY, FALSE, TRUE, FALSE, TRUE, TRUE },
+ { "highway", "secondary",80,WAY_SECONDARY, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "secondary_link",60,WAY_SECONDARY, FALSE, TRUE, FALSE, TRUE, TRUE },
+ { "highway", "tertiary",60,WAY_TERTIARY, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "unclassified",50,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "byway",40,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "residential",40,WAY_RESIDENTIAL, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "service",20,WAY_SERVICE, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "track",20,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "unsurfaced",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "minor",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
+ { "highway", "pedestrian",20,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
+ { "highway", "footway",1,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
+ { "highway", "steps",0,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE},
+ { "highway", "bridleway",10,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
+ { "highway", "cycleway",10,WAY_CYCLEWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
+ { "railway", "rail",0,WAY_RAIL, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "aeroway", "runway",0,WAY_RUNWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "aeroway", "taxiway",0,WAY_TAXIWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "natural", "water",0,WAY_WATER, FALSE, FALSE, TRUE, FALSE, FALSE },
+ { "waterway", "river",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "waterway", "canal",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "waterway", "stream",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
+ { "building", "*",0,WAY_UNWAYED, FALSE, FALSE, TRUE, FALSE, FALSE },
+ { NULL, NULL, 0, WAY_UNWAYED, FALSE, FALSE, FALSE, FALSE, FALSE }
+};
+
+static sqlite3 *db;
+tag_parent_t tag_parent=IS_NONE;
+
+static GHashTable *osm_nodes;
+static GHashTable *osm_node_tags;
+static GHashTable *osm_way_tags;
+static GSList *osm_ways;
+static GSList *osm_poi;
+
+static GHashTable *osm_place_country;
+static GHashTable *osm_place_region;
+static GHashTable *osm_place_city;
+static GHashTable *osm_place_suburb;
+static GHashTable *osm_place_village;
+static GHashTable *osm_node_isin;
+static GHashTable *osm_way_isin;
+
+static node *cnode=NULL;
+static way *cway=NULL;
+
+struct sql_stmt {
+ sqlite3_stmt *insert_poi;
+ sqlite3_stmt *delete_osm_poi;
+
+ sqlite3_stmt *insert_node;
+ sqlite3_stmt *delete_nodes;
+ sqlite3_stmt *select_node;
+ sqlite3_stmt *update_node;
+
+ sqlite3_stmt *insert_way_data;
+ sqlite3_stmt *insert_way_ref;
+ sqlite3_stmt *insert_way_pc;
+ sqlite3_stmt *insert_way_name;
+ sqlite3_stmt *insert_way_names_nls;
+ sqlite3_stmt *insert_way_n2n;
+ sqlite3_stmt *delete_way;
+ sqlite3_stmt *delete_way_n2n;
+ sqlite3_stmt *delete_way_name;
+ sqlite3_stmt *delete_way_names_nls;
+ sqlite3_stmt *delete_way_ref;
+ sqlite3_stmt *delete_way_pc;
+
+ sqlite3_stmt *insert_place;
+ sqlite3_stmt *delete_place;
+};
+static struct sql_stmt sql;
+
+
+static struct map_bbox bbox;
+static gboolean use_bbox;
+
+void osm_free_way_data(way *w);
+void print_way(way *w);
+
+void db_prepare(sqlite3 *db);
+gboolean db_insert_node(node *n);
+guint32 osm_find_way_place(way *w, node_type_t nt);
+
+/****************************************************/
+/* Functions */
+/****************************************************/
+
+static void
+db_finalize(void)
+{
+sqlite3_finalize(sql.insert_poi);
+sqlite3_finalize(sql.delete_osm_poi);
+
+sqlite3_finalize(sql.insert_node);
+sqlite3_finalize(sql.select_node);
+sqlite3_finalize(sql.delete_nodes);
+sqlite3_finalize(sql.update_node);
+
+sqlite3_finalize(sql.insert_place);
+sqlite3_finalize(sql.delete_place);
+
+sqlite3_finalize(sql.delete_way);
+sqlite3_finalize(sql.insert_way_data);
+
+sqlite3_finalize(sql.delete_way_name);
+sqlite3_finalize(sql.insert_way_name);
+
+sqlite3_finalize(sql.delete_way_n2n);
+sqlite3_finalize(sql.insert_way_n2n);
+
+sqlite3_finalize(sql.delete_way_pc);
+sqlite3_finalize(sql.insert_way_pc);
+
+sqlite3_finalize(sql.delete_way_names_nls);
+sqlite3_finalize(sql.insert_way_names_nls);
+}
+
+void
+db_prepare(sqlite3 *db)
+{
+/* Way nodes */
+sqlite3_prepare_v2(db, "insert or replace into nodes (nid,ilat,ilon,rlat,rlon,l,f) values (?,?,?,?,?,0,?)", -1, &sql.insert_node, NULL);
+sqlite3_prepare_v2(db, "select ilat,ilon,l from nodes where nid=?", -1, &sql.select_node, NULL);
+sqlite3_prepare_v2(db, "delete from nodes", -1, &sql.delete_nodes, NULL);
+sqlite3_prepare_v2(db, "update nodes set l=l+1 where nid=?", -1, &sql.update_node, NULL);
+
+/* Places */
+sqlite3_prepare_v2(db, "insert or replace into places (nid,type,name,isin_c,isin_p) values (?, ?, ?, ?, ?)", -1, &sql.insert_place, NULL);
+sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_place, NULL);
+
+/* POI nodes */
+if (sqlite3_prepare_v2(db, "insert or replace into poi (osm_id, lat, lon, label, cat_id, public, source, priority, isin_c, isin_p, desc, url, postal_code) "
+ " values (?, ?, ?, ?, ?, 1, 1, ?, ?, ?, ?, ?, ?)", -1, &sql.insert_poi, NULL)!=SQLITE_OK)
+ g_printf("SQL: %s\n", sqlite3_errmsg(db));
+
+sqlite3_prepare_v2(db, "delete from poi where osm_id>0 and source=1", -1, &sql.delete_osm_poi, NULL);
+
+/* Ways */
+sqlite3_prepare_v2(db, "insert or replace into way (wid,nodes,type,flags,speed,isin_c,isin_p,lat,lon) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", -1, &sql.insert_way_data, NULL);
+sqlite3_prepare_v2(db, "delete from way", -1, &sql.delete_way, NULL);
+
+/* Way nodes */
+sqlite3_prepare_v2(db, "insert into way_n2n (wid,f,t) values (?,?,?)", -1, &sql.insert_way_n2n, NULL);
+sqlite3_prepare_v2(db, "delete from way_n2n where wid=?", -1, &sql.delete_way_n2n, NULL);
+
+/* Way names */
+sqlite3_prepare_v2(db, "insert or replace into way_names (wid,name,norm) values (?, ?, ?)", -1, &sql.insert_way_name, NULL);
+sqlite3_prepare_v2(db, "delete from way_names", -1, &sql.delete_way_name, NULL);
+
+/* Way postal codes */
+sqlite3_prepare_v2(db, "insert or replace into way_pc (wid,pc) values (?, ?)", -1, &sql.insert_way_pc, NULL);
+sqlite3_prepare_v2(db, "delete from way_pc", -1, &sql.delete_way_pc, NULL);
+
+/* Other language names for ways */
+sqlite3_prepare_v2(db, "insert into way_names_nls (wid,lang,name, norm) values (?, ?, ?, ?)", -1, &sql.insert_way_names_nls, NULL);
+sqlite3_prepare_v2(db, "delete from way_names_nls where wid=?", -1, &sql.delete_way_names_nls, NULL);
+
+/* Way ref and int_ref */
+sqlite3_prepare_v2(db, "insert or replace into way_ref (rid,ref,int_ref) values (?, ?, ?)", -1, &sql.insert_way_ref, NULL);
+sqlite3_prepare_v2(db, "delete from way_ref", -1, &sql.delete_way_ref, NULL);
+}
+
+/********************************************************************/
+
+void
+print_way(way *w)
+{
+#ifdef VERBOSE
+g_assert(w);
+g_printf("Way #%d(N:%d T:%d S:%d IS: %d/%d): %s [%s:%s:%s]\n",
+ w->id,
+ g_slist_length(w->nodes),
+ w->type,
+ w->data ? w->data->speed : 0,
+ w->data ? w->data->isin_c : -1,
+ w->data ? w->data->isin_p : -1,
+ w->data ? w->data->name ? w->data->name : "" : "",
+ w->flags & W_ONEWAY ? "-" : "=",
+ w->flags & W_ROUNDABOUT ? "O" : "-",
+ w->flags & W_LINK ? "|" : " ");
+#endif
+}
+
+void
+print_node(node *n)
+{
+#ifdef VERBOSE
+g_assert(n);
+g_printf("Node #%d: T:%d IS: %d/%d [%s]\n",
+ n->id,
+ n->type,
+ n->data ? n->data->isin_c : -1,
+ n->data ? n->data->isin_p : -1,
+ n->data ? n->data->name : "");
+#endif
+}
+
+/********************************************************************/
+
+gboolean
+db_insert_node(node *n)
+{
+gint32 lat, lon;
+
+g_assert(n);
+
+lat=lat2mp_int(n->lat);
+lon=lon2mp_int(n->lon);
+
+sqlite3_bind_int(sql.insert_node, 1, n->id);
+
+/* Projected and integerized lat/lot */
+sqlite3_bind_int(sql.insert_node, 2, lat);
+sqlite3_bind_int(sql.insert_node, 3, lon);
+/* Original */
+sqlite3_bind_double(sql.insert_node, 4, n->lat);
+sqlite3_bind_double(sql.insert_node, 5, n->lon);
+sqlite3_bind_int(sql.insert_node, 6, n->type);
+
+db_exec(db, sql.insert_node);
+
+return TRUE;
+}
+
+static gboolean
+db_insert_place(node *n)
+{
+g_assert(n);
+if (!n->data)
+ return FALSE;
+if (!n->data->name)
+ return FALSE;
+sqlite3_bind_int(sql.insert_place, 1, n->id);
+sqlite3_bind_int(sql.insert_place, 2, n->type);
+sqlite3_bind_text(sql.insert_place, 3, n->data->name, -1, SQLITE_TRANSIENT);
+sqlite3_bind_int(sql.insert_place, 4, n->data->isin_p);
+sqlite3_bind_int(sql.insert_place, 5, n->data->isin_c);
+
+return db_exec(db,sql.insert_place);
+}
+
+static gboolean
+db_insert_poi(node *n)
+{
+g_assert(n);
+sqlite3_bind_int(sql.insert_poi, 1, n->id);
+sqlite3_bind_double(sql.insert_poi, 2, n->lat);
+sqlite3_bind_double(sql.insert_poi, 3, n->lon);
+if (n->data->name)
+ sqlite3_bind_text(sql.insert_poi, 4, n->data->name, -1, SQLITE_TRANSIENT);
+else
+ sqlite3_bind_text(sql.insert_poi, 4, "", -1, SQLITE_TRANSIENT);
+sqlite3_bind_int(sql.insert_poi, 5, n->type);
+sqlite3_bind_int(sql.insert_poi, 6, n->type/100);
+sqlite3_bind_int(sql.insert_poi, 7, n->data->isin_c);
+sqlite3_bind_int(sql.insert_poi, 8, n->data->isin_p);
+
+if (n->data->desc)
+ sqlite3_bind_text(sql.insert_poi, 9, n->data->desc, -1, SQLITE_TRANSIENT);
+if (n->data->url)
+ sqlite3_bind_text(sql.insert_poi, 10, n->data->url, -1, SQLITE_TRANSIENT);
+if (n->data->postal_code)
+ sqlite3_bind_text(sql.insert_poi, 11, n->data->postal_code, -1, SQLITE_TRANSIENT);
+
+return db_exec(db,sql.insert_poi);
+}
+
+/**
+ * Update node usage count
+ */
+static gboolean
+db_update_node_links(node *n)
+{
+g_assert(n);
+sqlite3_bind_int(sql.update_node, 1, n->id);
+
+return db_exec(db,sql.update_node);
+}
+
+/**
+ * Insert way,node1,node2 triplet
+ */
+static gboolean
+db_insert_way_n2n(way *w, node *nf, node *nt)
+{
+if (!w) {
+ g_printf("NULL WAY\n");
+ return FALSE;
+}
+
+if (!nf) {
+ g_printf("NULL NODE 1\n");
+ return FALSE;
+}
+
+if (!nt) {
+ g_printf("NULL NODE 2\n");
+ return FALSE;
+}
+
+sqlite3_bind_int(sql.insert_way_n2n, 1, w->id);
+sqlite3_bind_int(sql.insert_way_n2n, 2, nf->id);
+sqlite3_bind_int(sql.insert_way_n2n, 3, nt->id);
+
+#ifdef VERBOSE_N2N
+g_printf("%d [%d - %d]\n", w->id, nf->id, nt->id);
+#endif
+
+db_exec(db,sql.insert_way_n2n);
+db_update_node_links(nf);
+db_update_node_links(nt);
+return TRUE;
+}
+
+/**
+ * Insert way ref and int_ref
+ */
+static void
+db_insert_way_ref(way *w)
+{
+if (!w->data)
+ return;
+
+if (!w->data->ref && !w->data->int_ref)
+ return;
+
+way_refs++;
+
+sqlite3_bind_int(sql.insert_way_ref, 1, w->id);
+if (w->data->ref)
+ sqlite3_bind_text(sql.insert_way_ref, 2, w->data->ref, -1, SQLITE_TRANSIENT);
+if (w->data->int_ref)
+ sqlite3_bind_text(sql.insert_way_ref, 3, w->data->int_ref, -1, SQLITE_TRANSIENT);
+
+db_exec(db,sql.insert_way_ref);
+}
+
+/**
+ * Insert way name
+ */
+static void
+db_insert_way_name(way *w)
+{
+gchar *norm;
+
+if (!w->data)
+ return;
+if (!w->data->name)
+ return;
+
+way_names++;
+
+sqlite3_bind_int(sql.insert_way_name, 1, w->id);
+sqlite3_bind_text(sql.insert_way_name, 2, w->data->name, -1, SQLITE_TRANSIENT);
+
+#ifdef TRANSLIT_NAMES
+norm=g_convert(w->data->name, -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
+if (norm && strcmp(w->data->name, norm)!=0) {
+ sqlite3_bind_text(sql.insert_way_name, 3, norm, -1, SQLITE_TRANSIENT);
+}
+if (norm)
+ g_free(norm);
+#endif
+
+db_exec(db,sql.insert_way_name);
+}
+
+static void
+db_delete_way_names_nls(way *w)
+{
+sqlite3_bind_int(sql.delete_way_names_nls, 1, w->id);
+db_exec(db,sql.delete_way_names_nls);
+}
+
+static void
+db_insert_way_pc(way *w)
+{
+if (!w->data)
+ return;
+if (!w->data->postal_code)
+ return;
+
+sqlite3_bind_int(sql.insert_way_pc, 1, w->id);
+sqlite3_bind_text(sql.insert_way_pc, 2, w->data->postal_code, -1, SQLITE_TRANSIENT);
+
+db_exec(db,sql.insert_way_pc);
+}
+
+static void
+db_delete_way_pc(way *w)
+{
+sqlite3_bind_int(sql.delete_way_pc, 1, w->id);
+db_exec(db,sql.delete_way_pc);
+}
+
+static void
+db_insert_way_names_nls_cb(gpointer key, gpointer value, gpointer user_data)
+{
+gchar *norm;
+
+way *w=(way *)user_data;
+
+sqlite3_bind_int(sql.insert_way_names_nls, 1, w->id);
+sqlite3_bind_text(sql.insert_way_names_nls, 2, (gchar *)key, -1, SQLITE_TRANSIENT);
+sqlite3_bind_text(sql.insert_way_names_nls, 3, (gchar *)value, -1, SQLITE_TRANSIENT);
+#ifdef TRANSLIT_NAMES
+norm=g_convert((gchar *value), -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
+if (norm && strcmp((gchar *)value, norm)!=0) {
+ sqlite3_bind_text(sql.insert_way_names_nls, 4, norm, -1, SQLITE_TRANSIENT);
+}
+if (norm)
+ g_free(norm);
+#endif
+db_exec(db,sql.insert_way_names_nls);
+}
+
+static void
+db_insert_way_names_nls(way *w)
+{
+if (!w->data)
+ return;
+if (!w->data->names)
+ return;
+
+g_hash_table_foreach(w->data->names, db_insert_way_names_nls_cb, w);
+}
+
+/**
+ * Insert all data for the given way
+ * - name
+ * - ref
+ * - nodes
+ *
+ */
+static gboolean
+db_insert_way(way *w)
+{
+GSList *iter;
+guint ncnt;
+node *wmn;
+
+if (!w)
+ return FALSE;
+
+/* Skip things we don't use (yet) */
+if (w->type==WAY_UNWAYED || w->type>WAY_ROAD_END)
+ return TRUE;
+
+/* Insert nodes */
+for (iter=w->nodes; iter!=NULL; iter=iter->next) {
+ if (!iter->next)
+ break;
+ db_insert_way_n2n(w, iter->data, iter->next->data);
+}
+
+if (w->id==0)
+ return FALSE;
+
+if (w->data) {
+ w->data->isin_p=osm_find_way_place(w, NODE_PLACE_CITY);
+ w->data->isin_c=osm_find_way_place(w, NODE_PLACE_COUNTRY);
+}
+
+print_way(w);
+
+/* Get middle node, use it as way location */
+ncnt=g_slist_length(w->nodes);
+if (ncnt>1)
+ wmn=g_slist_nth_data(w->nodes, ncnt/2);
+else
+ wmn=0;
+
+sqlite3_bind_int(sql.insert_way_data, 1, w->id);
+sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt);
+sqlite3_bind_int(sql.insert_way_data, 3, w->type);
+sqlite3_bind_int(sql.insert_way_data, 4, w->flags);
+if (w->data) {
+ sqlite3_bind_int(sql.insert_way_data, 5, w->data->speed);
+ sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin_c);
+ sqlite3_bind_int(sql.insert_way_data, 7, w->data->isin_p);
+}
+if (wmn) {
+ sqlite3_bind_double(sql.insert_way_data, 8, wmn->lat);
+ sqlite3_bind_double(sql.insert_way_data, 9, wmn->lon);
+} else {
+ g_printerr("Failed to get way location node!\n");
+}
+
+db_exec(db,sql.insert_way_data);
+
+db_insert_way_ref(w);
+db_insert_way_name(w);
+db_insert_way_names_nls(w);
+db_insert_way_pc(w);
+
+osm_free_way_data(w);
+return TRUE;
+}
+
+/********************************************************************/
+
+static gchar *
+get_attr_key_value(const gchar **p, gchar *key)
+{
+gchar **d;
+
+d=p;
+while (*d!=NULL) {
+ if (strncmp(*d, key, strlen(key))==0) {
+ d++;
+ return *d;
+ }
+ d++;
+ d++;
+}
+return NULL;
+}
+
+static tag_state_t
+check_tag(const gchar *tag)
+{
+if (strcmp(tag,"node")==0) return IN_NODE_TAG;
+else if (strcmp(tag,"nd")==0) return IN_WNODE_TAG;
+else if (strcmp(tag,"way")==0) return IN_WAY_TAG;
+else if (strcmp(tag,"tag")==0) return IN_KEY_TAG;
+else if (strcmp(tag,"osm")==0) return IN_OSM_TAG;
+else if (strcmp(tag,"bound")==0) return IN_BOUND_TAG;
+else if (strcmp(tag,"relation")==0) return IN_RELATION_TAG;
+else if (strcmp(tag,"member")==0) return IN_MEMBER_TAG;
+else return ERROR;
+}
+
+static void
+find_nls_names(gpointer key, gpointer value, gpointer user_data)
+{
+gchar *k, *v;
+gchar *tmp;
+GHashTable *nls;
+
+k=(gchar *)key;
+v=(gchar *)value;
+nls=(GHashTable *)user_data;
+
+/* Check if it is a name key, return if not. */
+if (g_str_has_prefix(k, "name:")==FALSE)
+ return;
+
+tmp=g_strrstr(k, ":");
+if (!tmp)
+ return;
+tmp++; /* skip : */
+if (*tmp==0)
+ return;
+g_hash_table_insert(nls, g_strdup(tmp), g_strdup(v));
+#ifdef VERBOSE
+g_printf("NLS(%s): [%s]\n", tmp, v);
+#endif
+}
+
+/********************************************************************/
+
+static void
+node_print (node *n)
+{
+g_assert(n);
+if (n->data) {
+ g_printf("N: %d [%f:%f][%s](%d)\n",
+ n->id, n->lat, n->lon,
+ n->data->name ? n->data->name : "-",
+ n->type);
+} else {
+ g_printf("N: %d [%f:%f]\n",
+ n->id, n->lat, n->lon);
+}
+}
+
+#ifdef DEBUG
+static void
+dump_array(const gchar **p)
+{
+char **d;
+
+d=p;
+while (*d!=NULL) {
+ g_printf("[%s]", *d);
+ d++;
+}
+g_print("\n");
+}
+#endif
+
+static inline gboolean
+osm_node_check_box(gdouble nlat, gdouble nlon)
+{
+if (use_bbox==FALSE)
+ return TRUE;
+return (nlat > bbox.lat_min && nlat < bbox.lat_max && nlon > bbox.lon_min && nlon < bbox.lon_max) ? TRUE : FALSE;
+}
+
+static void
+osm_new_node_data(node *n)
+{
+if (n==NULL)
+ return;
+if (n->data!=NULL)
+ return;
+n->data=g_slice_new(node_data);
+n->data->name=NULL;
+n->data->url=NULL;
+n->data->desc=NULL;
+n->data->postal_code=NULL;
+n->type=NODE_PLAIN;
+noded_cnt++;
+}
+
+static void
+osm_free_node_data(node *n)
+{
+g_assert(n);
+g_assert(n->data);
+if (n->data->name)
+ g_free(n->data->name);
+if (n->data->url)
+ g_free(n->data->url);
+if (n->data->desc)
+ g_free(n->data->desc);
+if (n->data->postal_code)
+ g_free(n->data->postal_code);
+g_slice_free(node_data, n->data);
+n->data=NULL;
+noded_cnt--;
+}
+
+static node *
+osm_new_node(gint id, gdouble lat, gdouble lon)
+{
+node *n=NULL;
+
+n=g_slice_new(node);
+g_assert(n);
+n->id=id;
+n->lat=lat;
+n->lon=lon;
+n->data=(node_data *)NULL;
+return n;
+}
+
+static void
+osm_free_node(node *n)
+{
+g_assert(n);
+g_slice_free(node, n);
+}
+
+static node *
+osm_find_node(guint32 nid)
+{
+node *n;
+
+g_assert(osm_nodes);
+n=g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
+#if 0
+if (!n)
+ g_printerr("ERROR: Node %d not found!\n", nid);
+#endif
+return n;
+}
+
+static void
+osm_new_way_data(way *w)
+{
+if (w==NULL)
+ return;
+if (w->data!=NULL)
+ return;
+
+w->data=g_slice_new(way_data);
+w->data->name=NULL;
+w->data->names=NULL;
+w->data->ref=NULL;
+w->data->int_ref=NULL;
+w->data->postal_code=NULL;
+w->data->layer=0;
+w->data->speed=0;
+}
+
+void
+osm_free_way_data(way *w)
+{
+g_assert(w);
+if (!w->data)
+ return;
+if (w->data->name)
+ g_free(w->data->name);
+if (w->data->ref)
+ g_free(w->data->ref);
+if (w->data->int_ref)
+ g_free(w->data->int_ref);
+g_slice_free(way_data, w->data);
+w->data=NULL;
+}
+
+static way *
+osm_new_way(gint id)
+{
+way *w;
+
+w=g_slice_new(way);
+g_assert(w);
+w->id=id;
+w->nodes=NULL;
+w->type=WAY_UNWAYED;
+w->data=NULL;
+w->ncnt=0;
+w->flags=0;
+
+/* Add to list of ways */
+return w;
+}
+
+static void
+osm_way_add_to_list(way *w)
+{
+g_assert(w);
+osm_ways=g_slist_prepend(osm_ways, w);
+}
+
+static void
+osm_way_new_node(way *w, gint nid)
+{
+node *n;
+
+g_assert(w);
+n=osm_find_node(nid);
+w->nodes=g_slist_prepend(w->nodes, n);
+w->ncnt++;
+}
+
+/**
+ * Search the place hash table for the location of the node.
+ *
+ */
+static guint32
+osm_find_node_place(node *n)
+{
+node *t;
+gchar **isin;
+gchar **place;
+
+if (!n->data)
+ return 0;
+
+isin=g_hash_table_lookup(osm_node_isin, GINT_TO_POINTER(n->id));
+
+if (!isin)
+ return 0;
+
+place=isin;
+while (*place!=NULL) {
+ gchar *ps;
+ ps=g_strstrip(*place);
+#ifdef VERBOSE
+ g_printf("Checking (%d) [%s] in [%s]\n",n->type, n->data->name, ps);
+#endif
+ switch (n->type) {
+ case NODE_PLACE_CITY:
+ case NODE_PLACE_TOWN:
+ case NODE_PLACE_VILLAGE:
+ case NODE_PLACE_HAMLET:
+ t=g_hash_table_lookup(osm_place_region, ps);
+ if (t)
+ return t->id;
+ t=g_hash_table_lookup(osm_place_country, ps);
+ if (t)
+ return t->id;
+ break;
+ case NODE_PLACE_SUBURB:
+ case NODE_PLACE_LOCALITY:
+ t=g_hash_table_lookup(osm_place_city, ps);
+ if (t)
+ return t->id;
+ break;
+ case NODE_PLACE_ISLAND:
+ return 0;
+ break;
+ default:
+ t=g_hash_table_lookup(osm_place_city, ps);
+ if (t)
+ return t->id;
+ break;
+ }
+ place++;
+}
+
+return 0;
+}
+
+guint32
+osm_find_way_place(way *w, node_type_t nt)
+{
+gchar **isin;
+gchar **place;
+
+isin=g_hash_table_lookup(osm_way_isin, GINT_TO_POINTER(w->id));
+if (!isin)
+ return 0;
+
+place=isin;
+while (*place!=NULL) {
+ node *t;
+ gchar *ps;
+
+ ps=g_strstrip(*place);
+
+#ifdef VERBOSE
+ g_printf("Checking (%d) in [%s]\n",w->id, ps);
+#endif
+switch (nt) {
+ case NODE_PLACE_CITY:
+ case NODE_PLACE_TOWN:
+ case NODE_PLACE_VILLAGE:
+ case NODE_PLACE_HAMLET:
+ case NODE_PLACE_LOCALITY:
+ t=g_hash_table_lookup(osm_place_city, ps);
+ if (t)
+ return t->id;
+ break;
+ case NODE_PLACE_COUNTRY:
+ t=g_hash_table_lookup(osm_place_country, ps);
+ if (t)
+ return t->id;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ place++;
+}
+
+return 0;
+}
+
+/***********************************************************************/
+
+static void
+osm_node_save_node(gint key, gpointer value, gpointer user_data)
+{
+node *n=(node *)value;
+
+dbnode_cnt++;
+db_insert_node(n);
+if (dbnode_cnt % 26214==0)
+ g_printf("\rNodes: %f%%\n",((float)dbnode_cnt/(float)node_cnt)*100);
+}
+
+/**
+ * Check node type and insert as POI or Place
+ * Discard extra data after insert.
+ */
+static gboolean
+osm_node_save_poi(node *n, gpointer user_data)
+{
+if (!n) {
+ g_printerr("ERROR: null poi\n");
+ return FALSE;
+}
+
+if (!n->data) {
+ g_printerr("POI node with no data ?\n");
+ return FALSE;
+}
+
+n->data->isin_p=osm_find_node_place(n);
+n->data->isin_c=0;
+
+if (n->type>NODE_POI_START && n->type<NODE_POI_END) {
+ print_node(n);
+ db_insert_poi(n);
+ osm_free_node_data(n);
+} else if (n->type>NODE_PLACE_START && n->type<NODE_PLACE_END) {
+ print_node(n);
+ db_insert_place(n);
+} else {
+ osm_free_node_data(n);
+ return FALSE;
+}
+
+return TRUE;
+}
+
+static gboolean
+osm_planet_poi_clear_nodes(void)
+{
+g_print("Removing old OSM POIs...\n");
+db_transaction_begin(db);
+sqlite3_step(sql.delete_osm_poi);
+sqlite3_step(sql.delete_place);
+return db_transaction_commit(db);
+}
+
+static gboolean
+osm_planet_poi_save_nodes(void)
+{
+g_print("Storing new POIs...\n");
+db_transaction_begin(db);
+g_slist_foreach(osm_poi, osm_node_save_poi, NULL);
+g_slist_free(osm_poi);
+return db_transaction_commit(db);
+}
+
+/*********************************************************************/
+
+static void
+osm_planet_clear_nodes(void)
+{
+g_print("Clearing old nodes\n");
+sqlite3_step(sql.delete_nodes);
+}
+
+static gboolean
+osm_planet_save_nodes(void)
+{
+g_print("Storing nodes\n");
+db_transaction_begin(db);
+g_hash_table_foreach(osm_nodes, osm_node_save_node, NULL);
+return db_transaction_commit(db);
+}
+
+/*********************************************************************/
+
+static void
+osm_way_save(way *value, gpointer user_data)
+{
+dbway_cnt++;
+db_insert_way(value);
+if (dbway_cnt % 16384==0 && dbway_cnt>0) {
+ g_printf("\rWays: %f%%\n",(((float)dbway_cnt/(float)way_cnt)*100));
+ print_way(value);
+}
+}
+
+static void
+osm_planet_clear_ways(void)
+{
+g_print("Clearing old data\n");
+sqlite3_step(sql.delete_way);
+sqlite3_step(sql.delete_way_name);
+sqlite3_step(sql.delete_way_ref);
+sqlite3_step(sql.delete_way_n2n);
+}
+
+static gboolean
+osm_planet_save_ways(void)
+{
+g_print("Inserting new ways\n");
+db_transaction_begin(db);
+g_slist_foreach(osm_ways, osm_way_save, NULL);
+return db_transaction_commit(db);
+}
+
+/*********************************************************************/
+
+static void
+osm_planet_save_all_nodes(void)
+{
+g_printf("Saving planet nodes to database:\n");
+
+osm_planet_poi_clear_nodes();
+osm_planet_poi_save_nodes();
+
+if (!is_update) {
+ osm_planet_clear_nodes();
+ osm_planet_clear_ways();
+}
+osm_planet_save_nodes();
+}
+
+static void
+osm_planet_save_all_ways(void)
+{
+g_printf("Saving planet way to database:\n");
+
+osm_planet_save_ways();
+}
+
+/***********************************************************************/
+
+static void
+_osm_tag_start(void *userData, const char *name, const char **atts)
+{
+tag_state_t t;
+gchar *k, *v;
+guint32 id, ndref;
+gdouble nlat, nlon;
+
+t=check_tag(name);
+switch (t) {
+ case IN_OSM_TAG:
+ g_printf("Starting...\n");
+ break;
+ case IN_NODE_TAG:
+ tag_parent=IS_NODE;
+ node_cnt++;
+
+ id=atoi(get_attr_key_value(atts, "id"));
+ nlat=atof(get_attr_key_value(atts, "lat"));
+ nlon=atof(get_attr_key_value(atts, "lon"));
+
+ cnode=osm_new_node(id, nlat, nlon);
+ osm_node_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ break;
+ case IN_WAY_TAG:
+ tag_parent=IS_WAY;
+ way_cnt++;
+ id=atoi(get_attr_key_value(atts, "id"));
+ cway=osm_new_way(id);
+ osm_way_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ break;
+ case IN_WNODE_TAG:
+ ndref=atoi(get_attr_key_value(atts, "ref"));
+ if (use_bbox==TRUE) {
+ if (osm_find_node(ndref)==NULL) {
+ cway->id=0;
+ return;
+ }
+ }
+ osm_way_new_node(cway, ndref);
+ break;
+ case IN_KEY_TAG:
+ k=get_attr_key_value(atts, "k");
+ if (strcmp(k,"created_by")==0)
+ return;
+ if (strcmp(k,"source")==0)
+ return;
+
+ v=get_attr_key_value(atts, "v");
+#ifdef VERBOSE_KEYS
+ g_printf("TAG: K=[%s] V=[%s]\n", k, v);
+#endif
+
+ switch (tag_parent) {
+ case IS_NONE:
+ g_printf("Tag key/value pair but unknown owner\n");
+ break;
+ case IS_NODE:
+ {
+ if (!osm_node_tags)
+ return;
+
+ /* Insert key/value pairs into hash table */
+ if (cnode==NULL) {
+ g_printerr("In node tags but node is NULL!\n");
+ return;
+ }
+ g_hash_table_insert(osm_node_tags, g_strdup(k), g_strdup(v));
+ }
+ break;
+ case IS_WAY:
+ {
+ if (cway==NULL) {
+ g_printerr("In way tags but way is NULL!\n");
+ return;
+ }
+ g_hash_table_insert(osm_way_tags, g_strdup(k), g_strdup(v));
+ osm_new_way_data(cway);
+ }
+ break;
+ case IS_RELATION:
+
+ break;
+ }
+ break;
+ case IN_BOUND_TAG:
+ /* Ignore for now */
+ g_printf("Ignoring bound tag\n");
+ break;
+ case IN_RELATION_TAG:
+ tag_parent=IS_RELATION;
+
+ break;
+ case IN_MEMBER_TAG:
+
+ break;
+ default:
+ tag_parent=IS_NONE;
+ g_printf("Unknown tag: %s\n", name);
+ break;
+}
+}
+
+static void
+_osm_tag_end(void *userData, const char *name)
+{
+tag_state_t t;
+gchar *v;
+guint i;
+t=check_tag(name);
+switch (t) {
+ case IN_NODE_TAG:
+
+ if (node_cnt % 262140==0) {
+ g_printf("Nodes: %d of %d, POIs: %d, Outside box: %d\n", node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
+ }
+
+ if (!osm_node_tags)
+ return;
+
+ osm_new_node_data(cnode);
+
+ for (i=0; nodeinfo[i].k; i++) {
+ v=g_hash_table_lookup(osm_node_tags, nodeinfo[i].k);
+ if (!v)
+ continue;
+ if (strcasecmp (v, nodeinfo[i].v)==0) {
+ cnode->type=nodeinfo[i].type;
+ break;
+ }
+ }
+
+ /* Check if node is inside bounding box, if not skip it.
+ * But keep it if it's something we might need for other nodes:
+ * - Places (for is_in)
+ * - ...
+ */
+ if ((osm_node_check_box(cnode->lat, cnode->lon)==FALSE) &&
+ (cnode->type<NODE_PLACE_START)) {
+ osm_free_node_data(cnode);
+ osm_free_node(cnode);
+ g_hash_table_destroy(osm_node_tags);
+ node_skip_cnt++;
+ return;
+ }
+
+ g_hash_table_insert(osm_nodes, GINT_TO_POINTER(cnode->id), cnode);
+
+ if (cnode->type!=NODE_PLAIN) {
+ cnode->data->name=NULL;
+ v=g_hash_table_lookup(osm_node_tags, "name");
+ if (v)
+ cnode->data->name=g_strstrip(g_utf8_normalize(v, -1, G_NORMALIZE_ALL_COMPOSE));
+ v=g_hash_table_lookup(osm_node_tags, "note");
+ if (v)
+ cnode->data->desc=g_strstrip(g_strdup(v));
+ v=g_hash_table_lookup(osm_node_tags, "postal_code");
+ if (v)
+ cnode->data->postal_code=g_strstrip(g_strdup(v));
+
+ /* Links */
+ v=g_hash_table_lookup(osm_node_tags, "url");
+ if (v) {
+ cnode->data->url=g_strstrip(g_strdup(v));
+ } else {
+ v=g_hash_table_lookup(osm_node_tags, "wikipedia");
+ if (v && strncmp(v,"http:", 5)==0)
+ cnode->data->url=g_strstrip(g_strdup(v));
+ }
+ }
+
+ cnode->data->isin_c=0;
+ cnode->data->isin_p=0;
+ v=g_hash_table_lookup(osm_node_tags, "is_in");
+ if (v) {
+ gchar **isin;
+ isin=g_strsplit(v, ",", 10);
+ g_hash_table_insert(osm_node_isin, GINT_TO_POINTER(cnode->id), isin);
+ }
+
+ if (cnode->type==NODE_PLAIN) {
+ osm_free_node_data(cnode);
+ } else {
+ osm_poi=g_slist_prepend(osm_poi, cnode);
+ if (cnode->data->name) {
+ switch (cnode->type) {
+ case NODE_PLACE_COUNTRY:
+ g_hash_table_insert(osm_place_country, cnode->data->name, cnode);
+ break;
+ case NODE_PLACE_CITY:
+ case NODE_PLACE_TOWN:
+ g_hash_table_insert(osm_place_city, cnode->data->name, cnode);
+ break;
+ case NODE_PLACE_SUBURB:
+ g_hash_table_insert(osm_place_suburb, cnode->data->name, cnode);
+ break;
+ case NODE_PLACE_VILLAGE:
+ case NODE_PLACE_HAMLET:
+ case NODE_PLACE_LOCALITY:
+ g_hash_table_insert(osm_place_village, cnode->data->name, cnode);
+ break;
+ case NODE_PLACE_ISLAND:
+ /* Ignore for now */
+ break;
+ default:;
+ }
+ }
+ }
+ g_hash_table_destroy(osm_node_tags);
+ cnode=NULL;
+ break;
+ case IN_WAY_TAG:
+ if (way_cnt % 1024==0) {
+ g_printf("\rWays: %d\n", way_cnt);
+ }
+
+ cway->nodes=g_slist_reverse(cway->nodes);
+
+ for (i=0; wayinfo[i].k; i++) {
+ v=g_hash_table_lookup(osm_way_tags, wayinfo[i].k);
+ if (!v)
+ continue;
+ if (strcasecmp (v, wayinfo[i].v)==0) {
+ if (wayinfo[i].link==TRUE)
+ cway->flags|=W_LINK;
+ if (wayinfo[i].area==TRUE)
+ cway->flags|=W_AREA;
+ if (wayinfo[i].oneway==TRUE)
+ cway->flags|=W_ONEWAY;
+ cway->type=wayinfo[i].type;
+ if (cway->data->speed==0)
+ cway->data->speed=wayinfo[i].defspeed;
+ break;
+ }
+ }
+
+ v=g_hash_table_lookup(osm_way_tags, "name");
+ if (v) {
+ cway->data->name=g_utf8_normalize(v, -1, G_NORMALIZE_ALL_COMPOSE);
+ /* Try to find other language names */
+ cway->data->names=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_foreach(osm_way_tags, find_nls_names, cway->data->names);
+ if (g_hash_table_size(cway->data->names)==0) {
+ g_hash_table_destroy(cway->data->names);
+ cway->data->names=NULL;
+ }
+ }
+
+ v=g_hash_table_lookup(osm_way_tags, "ref");
+ if (v)
+ cway->data->ref=g_strdup(v);
+ v=g_hash_table_lookup(osm_way_tags, "int_ref");
+ if (v)
+ cway->data->int_ref=g_strdup(v);
+
+ v=g_hash_table_lookup(osm_way_tags, "postal_code");
+ if (v)
+ cway->data->postal_code=g_strdup(v);
+
+ /* XXX: somehow handle the silly -1 'reversed' oneway */
+ v=g_hash_table_lookup(osm_way_tags, "oneway");
+ if (v)
+ cway->flags|=W_ONEWAY;
+
+ v=g_hash_table_lookup(osm_way_tags, "noexit");
+ if (v)
+ cway->flags|=W_NOEXIT;
+
+ v=g_hash_table_lookup(osm_way_tags, "speedlimit");
+ if (v)
+ cway->data->speed=atoi(v);
+ v=g_hash_table_lookup(osm_way_tags, "maxspeed");
+ if (v)
+ cway->data->speed=atoi(v);
+
+#if 0
+ v=g_hash_table_lookup(osm_way_tags, "layer");
+ if (v)
+ cway->data->layer=atoi(v);
+#endif
+
+ v=g_hash_table_lookup(osm_way_tags, "junction");
+ if (v && strcasecmp(v,"roundabout")==0) {
+ cway->flags|=W_ROUNDABOUT;
+ cway->flags|=W_ONEWAY;
+ } else if (v && strcasecmp(v,"mini_roundabout")==0) {
+ cway->flags|=W_ROUNDABOUT;
+ cway->flags|=W_ONEWAY;
+ }
+
+ /* XXX: Should check keys */
+ v=g_hash_table_lookup(osm_way_tags, "access");
+ if (v && (strcasecmp(v, "private")==0)) {
+ cway->flags|=W_NOACCESS;
+ }
+
+ print_way(cway);
+
+ v=g_hash_table_lookup(osm_way_tags, "is_in");
+ if (v) {
+ gchar **isin;
+ isin=g_strsplit(v, ",", 10);
+ g_hash_table_insert(osm_way_isin, GINT_TO_POINTER(cway->id), isin);
+ }
+
+ if (cway->data && cway->data->name==NULL && cway->data->ref==NULL &&
+ cway->data->int_ref==NULL && cway->data->layer==0 && cway->data->speed==0)
+ osm_free_way_data(cway);
+
+ if (cway->id!=0)
+ osm_way_add_to_list(cway);
+
+ cway=NULL;
+ g_hash_table_destroy(osm_way_tags);
+ break;
+ case IN_BOUND_TAG:
+ /* */
+ break;
+ case IN_OSM_TAG:
+ g_printf("\nPlanet loaded.\n");
+ break;
+ default:;
+}
+}
+
+/************************************************************************/
+
+static void
+storage_init(void)
+{
+osm_nodes=g_hash_table_new(g_direct_hash, g_direct_equal);
+
+osm_place_country=g_hash_table_new(g_str_hash, g_str_equal);
+osm_place_city=g_hash_table_new(g_str_hash, g_str_equal);
+osm_place_suburb=g_hash_table_new(g_str_hash, g_str_equal);
+osm_place_village=g_hash_table_new(g_str_hash, g_str_equal);
+osm_place_region=g_hash_table_new(g_str_hash, g_str_equal);
+osm_node_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
+osm_way_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
+}
+
+static void
+storage_free(void)
+{
+g_hash_table_destroy(osm_nodes);
+
+g_hash_table_destroy(osm_place_country);
+g_hash_table_destroy(osm_place_city);
+g_hash_table_destroy(osm_place_suburb);
+g_hash_table_destroy(osm_place_village);
+g_hash_table_destroy(osm_place_region);
+g_hash_table_destroy(osm_node_isin);
+}
+
+
+/************************************************************************/
+
+static gint
+print_fail(const gchar *msg, gint ret)
+{
+g_printerr("ERROR: %s\n", msg);
+return ret;
+}
+
+/************************************************************************/
+
+static void
+print_memory_usage(void)
+{
+g_print("Memory usage per item:\n");
+g_printf("Node size: %d\n", (gint)sizeof(node));
+g_printf("NodeD size: %d\n", (gint)sizeof(node_data));
+g_printf("Way size: %d\n", (gint)sizeof(way));
+g_printf("WayD size: %d\n", (gint)sizeof(way_data));
+}
+
+/************************************************************************
+ * Public inteface
+ ************************************************************************/
+
+void
+osm_planet_parser_init(void)
+{
+xp=XML_ParserCreate(NULL);
+XML_SetElementHandler(xp, _osm_tag_start, _osm_tag_end);
+storage_init();
+}
+
+void
+osm_planet_parser_deinit(void)
+{
+XML_ParserFree(xp);
+storage_free();
+}
+
+gboolean
+osm_planet_parse_buffer(gchar *buffer, size_t r)
+{
+if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) {
+ g_printerr("Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(xp),
+ XML_ErrorString(XML_GetErrorCode(xp)));
+ return FALSE;
+}
+return TRUE;
+}
+
+gboolean
+osm_planet_parse_file(gchar *pfile)
+{
+FILE *f;
+BZFILE *b;
+int bzerror;
+int r;
+gchar buffer[FILE_BUFFER];
+gboolean res=TRUE;
+
+f=fopen(pfile, "r");
+if (!f) {
+ perror("fopen failed\n");
+ return FALSE;
+}
+
+b=BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
+if (bzerror != BZ_OK) {
+ g_printf("BZ2_bzReadOpen failed\n");
+ BZ2_bzReadClose(&bzerror, b);
+ return FALSE;
+}
+
+do {
+ r=BZ2_bzRead(&bzerror, b, buffer, FILE_BUFFER);
+ if ((bzerror!=BZ_STREAM_END) && (bzerror!=BZ_OK)) {
+ res=FALSE;
+ break;
+ }
+ if (!osm_planet_parse_buffer(buffer, r)) {
+ res=FALSE;
+ break;
+ }
+} while (bzerror==BZ_OK);
+
+BZ2_bzReadClose(&bzerror, b);
+fclose(f);
+return res;
+}
+
+void
+osm_import_set_bbox(gboolean use_bb, gdouble latmin, gdouble lonmin, gdouble latmax, gdouble lonmax)
+{
+use_bbox=use_bb;
+bbox.lat_min=latmin;
+bbox.lon_min=lonmin;
+bbox.lat_max=latmax;
+bbox.lon_max=lonmax;
+g_printf("Skipping data outside of box: %f,%f - %f,%f\n",
+ bbox.lat_min, bbox.lon_min, bbox.lat_max, bbox.lon_max);
+}
+
+gboolean
+osm_import(const gchar *planet, const gchar *database)
+{
+if (db_connect(&db, database)!=TRUE) {
+ g_printerr("Database open failed: %s", database);
+ return FALSE;
+}
+
+db_create_tables(db);
+db_create_indexes(db);
+db_prepare(db);
+
+osm_planet_parser_init();
+
+if (osm_planet_parse_file(planet)==FALSE) {
+ g_printerr("Failed to parse file: %s\n", planet);
+ return FALSE;
+}
+
+g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt);
+g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
+g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
+g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
+g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes));
+
+osm_planet_save_all_nodes();
+osm_planet_save_all_ways();
+osm_planet_parser_deinit();
+db_close(&db);
+return TRUE;
+}
+
--- /dev/null
+#ifndef _OSM_DB_IMPORT_H
+#define _OSM_DB_IMPORT_H
+
+#include <glib.h>
+
+/* POI or Place node extra data */
+typedef struct _node_data node_data;
+struct _node_data {
+ gchar *name;
+ gchar *desc;
+ gchar *url;
+ gchar *postal_code;
+ guint32 isin_c;
+ guint32 isin_p;
+};
+
+/* Node type */
+typedef struct _node node;
+struct _node {
+ guint32 id;
+ gdouble lat;
+ gdouble lon;
+ node_type_t type;
+ node_data *data;
+};
+
+/* Way data structure */
+typedef struct _way_data way_data;
+struct _way_data {
+ gchar *name;
+ GHashTable *names;
+ gchar *ref;
+ gchar *int_ref;
+ gchar *postal_code;
+ guint32 isin_c; /* Country */
+ guint32 isin_p; /* Primary (city, village) place */
+ guint speed;
+ gint8 layer;
+};
+
+/* Way structure */
+typedef struct _way way;
+struct _way {
+ guint32 id;
+ way_type_t type;
+ guint16 ncnt;
+ guint8 flags;
+ way_data *data;
+ GSList *nodes;
+};
+
+struct map_bbox {
+ gdouble lat_min;
+ gdouble lon_min;
+ gdouble lat_max;
+ gdouble lon_max;
+};
+
+void osm_import_set_bbox(gboolean use_bb, gdouble latmin, gdouble lonmin, gdouble latmax, gdouble lonmax);
+gboolean osm_import(const gchar *planet, const gchar *database);
+
+#endif
*/
/*
- * Utility to read OSM planet XML file and store it in a sqlite3 database.
- * Reads in all nodes (if used, skips nodes outside bounding box)
- * Special POI nodes are stored in POI table.
- * Place POI nodes are stored in place table.
- *
- * Ways are read in and their data (name, type, etc) are stored
- * in way, way_name and way_ref tables.
- *
- * Nodes used by they ways are stored in way_n2n table.
- *
- * ...
- *
+ * A simple CLI interface to the mapper planet2sqlite import code.
*/
#include <stdio.h>
#include <unistd.h>
+#include <stdlib.h>
#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <math.h>
#include <glib.h>
#include <glib/gstdio.h>
-#include <sqlite3.h>
-#include <expat.h>
-#include <bzlib.h>
#include "osm.h"
#include "latlon.h"
#include "db.h"
-
-
-#if 0
-#define VERBOSE
-#endif
-/* #define VERBOSE_KEYS */
-
-
-/* Use g_convert to transliterate names.. my iconv seems to be fucked so this didn't work... */
-/* #define TRANSLIT_NAMES */
-
-#define FILE_BUFFER 65535
+#include "osm-db-import.h"
#define OSM_DB_FILE "osm-planet.db"
-static guint node_cnt=0;
-static guint node_skip_cnt=0;
-static guint noded_cnt=0;
-static guint way_cnt=0;
-static guint way_names=0;
-static guint way_refs=0;
-
-static guint dbnode_cnt=0;
-static guint dbnoded_cnt=0;
-static guint dbway_cnt=0;
-
-static gboolean is_update=FALSE;
-static XML_Parser xp;
-
-/* POI or Place node extra data */
-typedef struct _node_data node_data;
-struct _node_data {
- gchar *name;
- gchar *desc;
- gchar *url;
- gchar *postal_code;
- guint32 isin_c;
- guint32 isin_p;
-};
-
-/* Node type */
-typedef struct _node node;
-struct _node {
- guint32 id;
- gdouble lat;
- gdouble lon;
- node_type_t type;
- node_data *data;
-};
-
-/* Way data structure */
-typedef struct _way_data way_data;
-struct _way_data {
- gchar *name;
- GHashTable *names;
- gchar *ref;
- gchar *int_ref;
- gchar *postal_code;
- guint32 isin_c; /* Country */
- guint32 isin_p; /* Primary (city, village) place */
- guint speed;
- gint8 layer;
-};
-
-/* Way structure */
-typedef struct _way way;
-struct _way {
- guint32 id;
- way_type_t type;
- guint16 ncnt;
- guint8 flags;
- way_data *data;
- GSList *nodes;
-};
-
-/* XML tag IDs */
-typedef enum {
- START,
- IN_OSM_TAG,
- IN_NODE_TAG,
- IN_WNODE_TAG,
- IN_WAY_TAG,
- IN_KEY_TAG,
- IN_BOUND_TAG,
- IN_RELATION_TAG,
- IN_MEMBER_TAG,
- END,
- ERROR
-} tag_state_t;
-
-/* Parent tag type */
-typedef enum {
- IS_NONE,
- IS_NODE,
- IS_WAY,
- IS_RELATION
-} tag_parent_t;
-
-/* Node types table */
-/* XXX: Add support for parent category */
-struct _nodeinfo {
- gchar *k, *v;
- node_type_t type;
-} nodeinfo[] = {
- { "amenity", "fuel", NODE_AMENITY_FUEL },
- { "amenity", "parking", NODE_AMENITY_PARKING },
-
- { "amenity", "pub", NODE_AMENITY_PUB },
- { "amenity", "nightclub", NODE_AMENITY_NIGHTCLUB },
- { "amenity", "biergarten", NODE_AMENITY_PUB },
- { "amenity", "cafe", NODE_AMENITY_CAFE },
- { "amenity", "fast_food", NODE_AMENITY_FOOD },
- { "amenity", "restaurant", NODE_AMENITY_FOOD },
-
- { "amenity", "telephone", NODE_AMENITY_TELEPHONE },
- { "amenity", "toilets", NODE_AMENITY_WC },
-
- { "amenity", "hospital", NODE_AMENITY_HOSPITAL },
- { "amenity", "doctors", NODE_AMENITY_HOSPITAL },
- { "amenity", "pharmacy", NODE_AMENITY_PHARMACY },
-
- { "amenity", "post_office", NODE_AMENITY_POST },
- { "amenity", "post_box", NODE_AMENITY_POST_BOX },
-
- { "amenity", "cinema", NODE_AMENITY_CINEMA },
- { "amenity", "theatre", NODE_AMENITY_THEATRE },
-
- { "amenity", "atm", NODE_AMENITY_ATM },
- { "amenity", "bank", NODE_AMENITY_BANK },
-
- { "amenity", "police", NODE_AMENITY_POLICE },
- { "amenity", "speed_trap", NODE_AMENITY_SPEEDCAM },
- { "amenity", "speed_camera", NODE_AMENITY_SPEEDCAM },
- { "amenity", "speed camera", NODE_AMENITY_SPEEDCAM },
-
- { "amenity", "place_of_worship",NODE_AMENITY_POW },
-
- { "amenity", "school", NODE_AMENITY_SCHOOL },
- { "amenity", "college", NODE_AMENITY_COLLEGE },
- { "amenity", "university", NODE_AMENITY_COLLEGE },
-
- { "amenity", "library", NODE_AMENITY_LIBRARY },
- { "amenity", "townhall", NODE_AMENITY_TOWNHALL },
-
- { "amenity", "supermarket", NODE_AMENITY_SHOP },
- { "amenity", "shopping_centre", NODE_AMENITY_SHOP },
- { "amenity", "shop", NODE_AMENITY_SHOP },
- { "amenity", "shops", NODE_AMENITY_SHOP },
- { "amenity", "shopping", NODE_AMENITY_SHOP },
- { "amenity", "shopping_mall",NODE_AMENITY_SHOP },
- { "amenity", "cycle_shop", NODE_AMENITY_SHOP },
- { "amenity", "bike_shop", NODE_AMENITY_SHOP },
- { "amenity", "coffee_shop", NODE_AMENITY_SHOP },
- { "amenity", "indoor_shopping_centre", NODE_AMENITY_SHOP },
- { "amenity", "farm_shop", NODE_AMENITY_SHOP },
- { "amenity", "tea_shop", NODE_AMENITY_SHOP },
-
- /* Shops */
- { "shop", "supermarket", NODE_AMENITY_SHOP },
- { "shop", "bakery", NODE_AMENITY_SHOP },
- { "shop", "alcohol", NODE_AMENITY_SHOP },
- { "shop", "butcher", NODE_AMENITY_SHOP },
- { "shop", "flowers", NODE_AMENITY_SHOP },
- { "shop", "clothing", NODE_AMENITY_SHOP },
- { "shop", "souvenir", NODE_AMENITY_SHOP },
- { "shop", "bicycles", NODE_AMENITY_SHOP },
- { "shop", "grocers", NODE_AMENITY_SHOP },
- { "shop", "newsagents", NODE_AMENITY_SHOP },
- { "shop", "convenience", NODE_AMENITY_SHOP },
- { "shop", "bakers", NODE_AMENITY_SHOP },
- { "shop", "garden_centre",NODE_AMENITY_SHOP },
- { "shop", "photography", NODE_AMENITY_SHOP },
- { "shop", "general_store",NODE_AMENITY_SHOP },
- { "shop", "food", NODE_AMENITY_SHOP },
- { "shop", "drinks", NODE_AMENITY_SHOP },
- { "shop", "pharmacy", NODE_AMENITY_PHARMACY },
-
- /* Sport */
- { "sport" , "swimming", NODE_SPORT_SWIMMING },
- { "sport" , "golf", NODE_SPORT_GOLF },
- { "sport" , "tennis", NODE_SPORT_TENNIS },
- { "sport" , "football", NODE_SPORT_FOOTBALL },
- { "sport" , "soccer", NODE_SPORT_SOCCER },
- { "sport" , "baskteball", NODE_SPORT_BASKETBALL },
- { "sport" , "rugby", NODE_SPORT_RUGBY },
- { "sport" , "skating", NODE_SPORT_SKATING },
- { "sport" , "hockey", NODE_SPORT_HOCKEY },
- { "sport" , "skateboard", NODE_SPORT_SKATEBOARD },
- { "sport" , "bowling", NODE_SPORT_BOWLING },
- { "sport" , "10pin", NODE_SPORT_BOWLING },
- { "sport" , "motor", NODE_SPORT_MOTOR },
- { "sport" , "shooting_range",NODE_SPORT_SHOOTING },
- { "sport" , "paintball", NODE_SPORT_PAINTBALL },
- { "sport" , "horse_racing",NODE_SPORT_HORSES },
- { "sport" , "horse", NODE_SPORT_HORSES },
- { "sport" , "horses", NODE_SPORT_HORSES },
- { "sport" , "dog_racing", NODE_SPORT_DOG },
- { "sport" , "pelota", NODE_SPORT_PELOTA },
- { "sport" , "racquet", NODE_SPORT_RACQUET },
- { "sport" , "equestrian", NODE_SPORT_HORSES },
- { "sport" , "baseball", NODE_SPORT_BASEBALL },
- { "sport" , "cricket", NODE_SPORT_CRICKET },
- { "sport" , "croquet", NODE_SPORT_CROQUET },
- { "sport" , "cycling", NODE_SPORT_CYCLING },
- { "sport" , "bowls", NODE_SPORT_BOWLS },
- { "sport" , "athletics", NODE_SPORT_ATHLETICS },
- { "sport" , "gymnastics", NODE_SPORT_GYMNASTICS },
- { "sport" , "multi", NODE_SPORT_OTHER },
- { "leisure", "sport_centre",NODE_SPORT_CENTER },
-
- /* Tourism */
- { "tourism", "information", NODE_TOURISM_INFO },
- { "tourism", "camp_site", NODE_TOURISM_CAMP_SITE },
- { "tourism", "caravan_site",NODE_TOURISM_CARAVAN_SITE },
- { "tourism", "picnic_site", NODE_TOURISM_PICNIC_SITE },
- { "tourism", "theme_park", NODE_TOURISM_THEME_PARK },
- { "tourism", "hotel", NODE_TOURISM_HOTEL },
- { "tourism", "motel", NODE_TOURISM_MOTEL },
- { "tourism", "hostel", NODE_TOURISM_HOSTEL },
- { "tourism", "attraction", NODE_TOURISM_ATTRACTION },
- { "tourism", "zoo", NODE_TOURISM_ATTRACTION },
-
- { "historic", "ruins", NODE_TOURISM_ATTRACTION },
- { "historic", "monument", NODE_TOURISM_ATTRACTION },
- { "historic", "memorial", NODE_TOURISM_ATTRACTION },
- { "historic", "museum", NODE_HISTORIC_MUSEUM },
- { "historic", "castle", NODE_HISTORIC_CASTLE },
-
- { "railway", "station", NODE_RAILWAY_STATION },
- { "railway", "halt", NODE_RAILWAY_HALT },
-
- { "aeroway", "terminal", NODE_AIRPORT_TERMINAL },
-
- /* Places */
- { "place", "city", NODE_PLACE_CITY },
- { "place", "town", NODE_PLACE_TOWN },
- { "place", "village", NODE_PLACE_VILLAGE },
- { "place", "hamlet", NODE_PLACE_HAMLET },
- { "place", "locality", NODE_PLACE_LOCALITY },
- { "place", "suburb", NODE_PLACE_SUBURB },
- { "place", "island", NODE_PLACE_ISLAND },
-
- { "highway", "traffic_signals", NODE_TRAFFIC_SIGNALS },
- { "highway", "motorway_junction", NODE_JUNCTION },
- { "highway", "services", NODE_AMENITY_PARKING },
- { "highway", "toll_booth", NODE_TOLLBOOTH },
- { "highway", "gate", NODE_GATE },
-
- { NULL, NULL, NODE_PLAIN }
-};
-
-/* Array to get id number and defaults for ways of different types */
-struct _wayinfo {
- gchar *k, *v;
- guint defspeed;
- way_type_t type;
- gboolean oneway, link, area, car, foot;
-} wayinfo[] = {
- { "highway", "motorway",120,WAY_MOTORWAY, TRUE, FALSE, FALSE, TRUE, FALSE },
- { "highway", "motorway_link",120,WAY_MOTORWAY, TRUE, TRUE, FALSE, TRUE, FALSE },
- { "highway", "trunk",100,WAY_TRUNK, FALSE, FALSE, FALSE, TRUE, FALSE },
- { "highway", "trunk_link",100,WAY_TRUNK, FALSE, TRUE, FALSE, TRUE, FALSE },
- { "highway", "primary",80,WAY_PRIMARY, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "primary_link",60,WAY_PRIMARY, FALSE, TRUE, FALSE, TRUE, TRUE },
- { "highway", "secondary",80,WAY_SECONDARY, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "secondary_link",60,WAY_SECONDARY, FALSE, TRUE, FALSE, TRUE, TRUE },
- { "highway", "tertiary",60,WAY_TERTIARY, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "unclassified",50,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "byway",40,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "residential",40,WAY_RESIDENTIAL, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "service",20,WAY_SERVICE, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "track",20,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "unsurfaced",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "minor",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
- { "highway", "pedestrian",20,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
- { "highway", "footway",1,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
- { "highway", "steps",0,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE},
- { "highway", "bridleway",10,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
- { "highway", "cycleway",10,WAY_CYCLEWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
- { "railway", "rail",0,WAY_RAIL, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "aeroway", "runway",0,WAY_RUNWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "aeroway", "taxiway",0,WAY_TAXIWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "natural", "water",0,WAY_WATER, FALSE, FALSE, TRUE, FALSE, FALSE },
- { "waterway", "river",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "waterway", "canal",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "waterway", "stream",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
- { "building", "*",0,WAY_UNWAYED, FALSE, FALSE, TRUE, FALSE, FALSE },
- { NULL, NULL, 0, WAY_UNWAYED, FALSE, FALSE, FALSE, FALSE, FALSE }
-};
-
-static sqlite3 *db;
-tag_parent_t tag_parent=IS_NONE;
-
-static GHashTable *osm_nodes;
-static GHashTable *osm_node_tags;
-static GHashTable *osm_way_tags;
-static GSList *osm_ways;
-static GSList *osm_poi;
-
-static GHashTable *osm_place_country;
-static GHashTable *osm_place_region;
-static GHashTable *osm_place_city;
-static GHashTable *osm_place_suburb;
-static GHashTable *osm_place_village;
-static GHashTable *osm_node_isin;
-static GHashTable *osm_way_isin;
-
-static node *cnode=NULL;
-static way *cway=NULL;
-
-struct sql_stmt {
- sqlite3_stmt *insert_poi;
- sqlite3_stmt *delete_osm_poi;
-
- sqlite3_stmt *insert_node;
- sqlite3_stmt *delete_nodes;
- sqlite3_stmt *select_node;
- sqlite3_stmt *update_node;
-
- sqlite3_stmt *insert_way_data;
- sqlite3_stmt *insert_way_ref;
- sqlite3_stmt *insert_way_pc;
- sqlite3_stmt *insert_way_name;
- sqlite3_stmt *insert_way_names_nls;
- sqlite3_stmt *insert_way_n2n;
- sqlite3_stmt *delete_way;
- sqlite3_stmt *delete_way_n2n;
- sqlite3_stmt *delete_way_name;
- sqlite3_stmt *delete_way_names_nls;
- sqlite3_stmt *delete_way_ref;
- sqlite3_stmt *delete_way_pc;
-
- sqlite3_stmt *insert_place;
- sqlite3_stmt *delete_place;
-};
-static struct sql_stmt sql;
-
-struct map_bbox {
- gdouble lat_min;
- gdouble lon_min;
- gdouble lat_max;
- gdouble lon_max;
-};
-static struct map_bbox bbox;
-static gboolean use_bbox;
-
-void osm_free_way_data(way *w);
-void print_way(way *w);
-
-void db_prepare(sqlite3 *db);
-gboolean db_insert_node(node *n);
-guint32 osm_find_way_place(way *w, node_type_t nt);
-
-/****************************************************/
-/* Functions */
-/****************************************************/
-
-static void
-db_finalize(void)
-{
-sqlite3_finalize(sql.insert_poi);
-sqlite3_finalize(sql.delete_osm_poi);
-
-sqlite3_finalize(sql.insert_node);
-sqlite3_finalize(sql.select_node);
-sqlite3_finalize(sql.delete_nodes);
-sqlite3_finalize(sql.update_node);
-
-sqlite3_finalize(sql.insert_place);
-sqlite3_finalize(sql.delete_place);
-
-sqlite3_finalize(sql.delete_way);
-sqlite3_finalize(sql.insert_way_data);
-
-sqlite3_finalize(sql.delete_way_name);
-sqlite3_finalize(sql.insert_way_name);
-
-sqlite3_finalize(sql.delete_way_n2n);
-sqlite3_finalize(sql.insert_way_n2n);
-
-sqlite3_finalize(sql.delete_way_pc);
-sqlite3_finalize(sql.insert_way_pc);
-
-sqlite3_finalize(sql.delete_way_names_nls);
-sqlite3_finalize(sql.insert_way_names_nls);
-}
-
-
-
-void
-db_prepare(sqlite3 *db)
-{
-/* Way nodes */
-sqlite3_prepare_v2(db, "insert or replace into nodes (nid,ilat,ilon,rlat,rlon,l,f) values (?,?,?,?,?,0,?)", -1, &sql.insert_node, NULL);
-sqlite3_prepare_v2(db, "select ilat,ilon,l from nodes where nid=?", -1, &sql.select_node, NULL);
-sqlite3_prepare_v2(db, "delete from nodes", -1, &sql.delete_nodes, NULL);
-sqlite3_prepare_v2(db, "update nodes set l=l+1 where nid=?", -1, &sql.update_node, NULL);
-
-/* Places */
-sqlite3_prepare_v2(db, "insert or replace into places (nid,type,name,isin_c,isin_p) values (?, ?, ?, ?, ?)", -1, &sql.insert_place, NULL);
-sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_place, NULL);
-
-/* POI nodes */
-if (sqlite3_prepare_v2(db, "insert or replace into poi (osm_id, lat, lon, label, cat_id, public, source, priority, isin_c, isin_p, desc, url, postal_code) "
- " values (?, ?, ?, ?, ?, 1, 1, ?, ?, ?, ?, ?, ?)", -1, &sql.insert_poi, NULL)!=SQLITE_OK)
- g_printf("SQL: %s\n", sqlite3_errmsg(db));
-
-sqlite3_prepare_v2(db, "delete from poi where osm_id>0 and source=1", -1, &sql.delete_osm_poi, NULL);
-
-/* Ways */
-sqlite3_prepare_v2(db, "insert or replace into way (wid,nodes,type,flags,speed,isin_c,isin_p,lat,lon) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", -1, &sql.insert_way_data, NULL);
-sqlite3_prepare_v2(db, "delete from way", -1, &sql.delete_way, NULL);
-
-/* Way nodes */
-sqlite3_prepare_v2(db, "insert into way_n2n (wid,f,t) values (?,?,?)", -1, &sql.insert_way_n2n, NULL);
-sqlite3_prepare_v2(db, "delete from way_n2n where wid=?", -1, &sql.delete_way_n2n, NULL);
-
-/* Way names */
-sqlite3_prepare_v2(db, "insert or replace into way_names (wid,name,norm) values (?, ?, ?)", -1, &sql.insert_way_name, NULL);
-sqlite3_prepare_v2(db, "delete from way_names", -1, &sql.delete_way_name, NULL);
-
-/* Way postal codes */
-sqlite3_prepare_v2(db, "insert or replace into way_pc (wid,pc) values (?, ?)", -1, &sql.insert_way_pc, NULL);
-sqlite3_prepare_v2(db, "delete from way_pc", -1, &sql.delete_way_pc, NULL);
-
-/* Other language names for ways */
-sqlite3_prepare_v2(db, "insert into way_names_nls (wid,lang,name, norm) values (?, ?, ?, ?)", -1, &sql.insert_way_names_nls, NULL);
-sqlite3_prepare_v2(db, "delete from way_names_nls where wid=?", -1, &sql.delete_way_names_nls, NULL);
-
-/* Way ref and int_ref */
-sqlite3_prepare_v2(db, "insert or replace into way_ref (rid,ref,int_ref) values (?, ?, ?)", -1, &sql.insert_way_ref, NULL);
-sqlite3_prepare_v2(db, "delete from way_ref", -1, &sql.delete_way_ref, NULL);
-}
-
-/********************************************************************/
-
-void
-print_way(way *w)
-{
-#ifdef VERBOSE
-g_assert(w);
-g_printf("Way #%d(N:%d T:%d S:%d IS: %d/%d): %s [%s:%s:%s]\n",
- w->id,
- g_slist_length(w->nodes),
- w->type,
- w->data ? w->data->speed : 0,
- w->data ? w->data->isin_c : -1,
- w->data ? w->data->isin_p : -1,
- w->data ? w->data->name ? w->data->name : "" : "",
- w->flags & W_ONEWAY ? "-" : "=",
- w->flags & W_ROUNDABOUT ? "O" : "-",
- w->flags & W_LINK ? "|" : " ");
-#endif
-}
-
-void
-print_node(node *n)
-{
-#ifdef VERBOSE
-g_assert(n);
-g_printf("Node #%d: T:%d IS: %d/%d [%s]\n",
- n->id,
- n->type,
- n->data ? n->data->isin_c : -1,
- n->data ? n->data->isin_p : -1,
- n->data ? n->data->name : "");
-#endif
-}
-
-/********************************************************************/
-
-gboolean
-db_insert_node(node *n)
-{
-gint32 lat, lon;
-
-g_assert(n);
-
-lat=lat2mp_int(n->lat);
-lon=lon2mp_int(n->lon);
-
-sqlite3_bind_int(sql.insert_node, 1, n->id);
-
-/* Projected and integerized lat/lot */
-sqlite3_bind_int(sql.insert_node, 2, lat);
-sqlite3_bind_int(sql.insert_node, 3, lon);
-/* Original */
-sqlite3_bind_double(sql.insert_node, 4, n->lat);
-sqlite3_bind_double(sql.insert_node, 5, n->lon);
-sqlite3_bind_int(sql.insert_node, 6, n->type);
-
-db_exec(db, sql.insert_node);
-
-return TRUE;
-}
-
-static gboolean
-db_insert_place(node *n)
-{
-g_assert(n);
-if (!n->data)
- return FALSE;
-if (!n->data->name)
- return FALSE;
-sqlite3_bind_int(sql.insert_place, 1, n->id);
-sqlite3_bind_int(sql.insert_place, 2, n->type);
-sqlite3_bind_text(sql.insert_place, 3, n->data->name, -1, SQLITE_TRANSIENT);
-sqlite3_bind_int(sql.insert_place, 4, n->data->isin_p);
-sqlite3_bind_int(sql.insert_place, 5, n->data->isin_c);
-
-return db_exec(db,sql.insert_place);
-}
-
-static gboolean
-db_insert_poi(node *n)
-{
-g_assert(n);
-sqlite3_bind_int(sql.insert_poi, 1, n->id);
-sqlite3_bind_double(sql.insert_poi, 2, n->lat);
-sqlite3_bind_double(sql.insert_poi, 3, n->lon);
-if (n->data->name)
- sqlite3_bind_text(sql.insert_poi, 4, n->data->name, -1, SQLITE_TRANSIENT);
-else
- sqlite3_bind_text(sql.insert_poi, 4, "", -1, SQLITE_TRANSIENT);
-sqlite3_bind_int(sql.insert_poi, 5, n->type);
-sqlite3_bind_int(sql.insert_poi, 6, n->type/100);
-sqlite3_bind_int(sql.insert_poi, 7, n->data->isin_c);
-sqlite3_bind_int(sql.insert_poi, 8, n->data->isin_p);
-
-if (n->data->desc)
- sqlite3_bind_text(sql.insert_poi, 9, n->data->desc, -1, SQLITE_TRANSIENT);
-if (n->data->url)
- sqlite3_bind_text(sql.insert_poi, 10, n->data->url, -1, SQLITE_TRANSIENT);
-if (n->data->postal_code)
- sqlite3_bind_text(sql.insert_poi, 11, n->data->postal_code, -1, SQLITE_TRANSIENT);
-
-return db_exec(db,sql.insert_poi);
-}
-
-/**
- * Update node usage count
- */
-static gboolean
-db_update_node_links(node *n)
-{
-g_assert(n);
-sqlite3_bind_int(sql.update_node, 1, n->id);
-
-return db_exec(db,sql.update_node);
-}
-
-/**
- * Insert way,node1,node2 triplet
- */
-static gboolean
-db_insert_way_n2n(way *w, node *nf, node *nt)
-{
-if (!w) {
- g_printf("NULL WAY\n");
- return FALSE;
-}
-
-if (!nf) {
- g_printf("NULL NODE 1\n");
- return FALSE;
-}
-
-if (!nt) {
- g_printf("NULL NODE 2\n");
- return FALSE;
-}
-
-sqlite3_bind_int(sql.insert_way_n2n, 1, w->id);
-sqlite3_bind_int(sql.insert_way_n2n, 2, nf->id);
-sqlite3_bind_int(sql.insert_way_n2n, 3, nt->id);
-
-#ifdef VERBOSE_N2N
-g_printf("%d [%d - %d]\n", w->id, nf->id, nt->id);
-#endif
-
-db_exec(db,sql.insert_way_n2n);
-db_update_node_links(nf);
-db_update_node_links(nt);
-return TRUE;
-}
-
-/**
- * Insert way ref and int_ref
- */
-static void
-db_insert_way_ref(way *w)
-{
-if (!w->data)
- return;
-
-if (!w->data->ref && !w->data->int_ref)
- return;
-
-way_refs++;
-
-sqlite3_bind_int(sql.insert_way_ref, 1, w->id);
-if (w->data->ref)
- sqlite3_bind_text(sql.insert_way_ref, 2, w->data->ref, -1, SQLITE_TRANSIENT);
-if (w->data->int_ref)
- sqlite3_bind_text(sql.insert_way_ref, 3, w->data->int_ref, -1, SQLITE_TRANSIENT);
-
-db_exec(db,sql.insert_way_ref);
-}
-
-/**
- * Insert way name
- */
-static void
-db_insert_way_name(way *w)
-{
-gchar *norm;
-
-if (!w->data)
- return;
-if (!w->data->name)
- return;
-
-way_names++;
-
-sqlite3_bind_int(sql.insert_way_name, 1, w->id);
-sqlite3_bind_text(sql.insert_way_name, 2, w->data->name, -1, SQLITE_TRANSIENT);
-
-#ifdef TRANSLIT_NAMES
-norm=g_convert(w->data->name, -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
-if (norm && strcmp(w->data->name, norm)!=0) {
- sqlite3_bind_text(sql.insert_way_name, 3, norm, -1, SQLITE_TRANSIENT);
-}
-if (norm)
- g_free(norm);
-#endif
-
-db_exec(db,sql.insert_way_name);
-}
-
-static void
-db_delete_way_names_nls(way *w)
-{
-sqlite3_bind_int(sql.delete_way_names_nls, 1, w->id);
-db_exec(db,sql.delete_way_names_nls);
-}
-
-static void
-db_insert_way_pc(way *w)
-{
-if (!w->data)
- return;
-if (!w->data->postal_code)
- return;
-
-sqlite3_bind_int(sql.insert_way_pc, 1, w->id);
-sqlite3_bind_text(sql.insert_way_pc, 2, w->data->postal_code, -1, SQLITE_TRANSIENT);
-
-db_exec(db,sql.insert_way_pc);
-}
-
-static void
-db_delete_way_pc(way *w)
-{
-sqlite3_bind_int(sql.delete_way_pc, 1, w->id);
-db_exec(db,sql.delete_way_pc);
-}
-
-static void
-db_insert_way_names_nls_cb(gpointer key, gpointer value, gpointer user_data)
-{
-gchar *norm;
-
-way *w=(way *)user_data;
-
-sqlite3_bind_int(sql.insert_way_names_nls, 1, w->id);
-sqlite3_bind_text(sql.insert_way_names_nls, 2, (gchar *)key, -1, SQLITE_TRANSIENT);
-sqlite3_bind_text(sql.insert_way_names_nls, 3, (gchar *)value, -1, SQLITE_TRANSIENT);
-#ifdef TRANSLIT_NAMES
-norm=g_convert((gchar *value), -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
-if (norm && strcmp((gchar *)value, norm)!=0) {
- sqlite3_bind_text(sql.insert_way_names_nls, 4, norm, -1, SQLITE_TRANSIENT);
-}
-if (norm)
- g_free(norm);
-#endif
-db_exec(db,sql.insert_way_names_nls);
-}
-
-static void
-db_insert_way_names_nls(way *w)
-{
-if (!w->data)
- return;
-if (!w->data->names)
- return;
-
-g_hash_table_foreach(w->data->names, db_insert_way_names_nls_cb, w);
-}
-
-/**
- * Insert all data for the given way
- * - name
- * - ref
- * - nodes
- *
- */
-static gboolean
-db_insert_way(way *w)
-{
-GSList *iter;
-guint ncnt;
-node *wmn;
-
-if (!w)
- return FALSE;
-
-/* Skip things we don't use (yet) */
-if (w->type==WAY_UNWAYED || w->type>WAY_ROAD_END)
- return TRUE;
-
-/* Insert nodes */
-for (iter=w->nodes; iter!=NULL; iter=iter->next) {
- if (!iter->next)
- break;
- db_insert_way_n2n(w, iter->data, iter->next->data);
-}
-
-if (w->id==0)
- return FALSE;
-
-if (w->data) {
- w->data->isin_p=osm_find_way_place(w, NODE_PLACE_CITY);
- w->data->isin_c=osm_find_way_place(w, NODE_PLACE_COUNTRY);
-}
-
-print_way(w);
-
-/* Get middle node, use it as way location */
-ncnt=g_slist_length(w->nodes);
-if (ncnt>1)
- wmn=g_slist_nth_data(w->nodes, ncnt/2);
-else
- wmn=0;
-
-sqlite3_bind_int(sql.insert_way_data, 1, w->id);
-sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt);
-sqlite3_bind_int(sql.insert_way_data, 3, w->type);
-sqlite3_bind_int(sql.insert_way_data, 4, w->flags);
-if (w->data) {
- sqlite3_bind_int(sql.insert_way_data, 5, w->data->speed);
- sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin_c);
- sqlite3_bind_int(sql.insert_way_data, 7, w->data->isin_p);
-}
-if (wmn) {
- sqlite3_bind_double(sql.insert_way_data, 8, wmn->lat);
- sqlite3_bind_double(sql.insert_way_data, 9, wmn->lon);
-} else {
- g_printerr("Failed to get way location node!\n");
-}
-
-db_exec(db,sql.insert_way_data);
-
-db_insert_way_ref(w);
-db_insert_way_name(w);
-db_insert_way_names_nls(w);
-db_insert_way_pc(w);
-
-osm_free_way_data(w);
-return TRUE;
-}
-
-/********************************************************************/
-
-static gchar *
-get_attr_key_value(const gchar **p, gchar *key)
-{
-gchar **d;
-
-d=p;
-while (*d!=NULL) {
- if (strncmp(*d, key, strlen(key))==0) {
- d++;
- return *d;
- }
- d++;
- d++;
-}
-return NULL;
-}
-
-static tag_state_t
-check_tag(const gchar *tag)
-{
-if (strcmp(tag,"node")==0) return IN_NODE_TAG;
-else if (strcmp(tag,"nd")==0) return IN_WNODE_TAG;
-else if (strcmp(tag,"way")==0) return IN_WAY_TAG;
-else if (strcmp(tag,"tag")==0) return IN_KEY_TAG;
-else if (strcmp(tag,"osm")==0) return IN_OSM_TAG;
-else if (strcmp(tag,"bound")==0) return IN_BOUND_TAG;
-else if (strcmp(tag,"relation")==0) return IN_RELATION_TAG;
-else if (strcmp(tag,"member")==0) return IN_MEMBER_TAG;
-else return ERROR;
-}
-
-static void
-find_nls_names(gpointer key, gpointer value, gpointer user_data)
-{
-gchar *k, *v;
-gchar *tmp;
-GHashTable *nls;
-
-k=(gchar *)key;
-v=(gchar *)value;
-nls=(GHashTable *)user_data;
-
-/* Check if it is a name key, return if not. */
-if (g_str_has_prefix(k, "name:")==FALSE)
- return;
-
-tmp=g_strrstr(k, ":");
-if (!tmp)
- return;
-tmp++; /* skip : */
-if (*tmp==0)
- return;
-g_hash_table_insert(nls, g_strdup(tmp), g_strdup(v));
-#ifdef VERBOSE
-g_printf("NLS(%s): [%s]\n", tmp, v);
-#endif
-}
-
-/********************************************************************/
-
-static void
-node_print (node *n)
-{
-g_assert(n);
-if (n->data) {
- g_printf("N: %d [%f:%f][%s](%d)\n",
- n->id, n->lat, n->lon,
- n->data->name ? n->data->name : "-",
- n->type);
-} else {
- g_printf("N: %d [%f:%f]\n",
- n->id, n->lat, n->lon);
-}
-}
-
-#ifdef DEBUG
-static void
-dump_array(const gchar **p)
-{
-char **d;
-
-d=p;
-while (*d!=NULL) {
- g_printf("[%s]", *d);
- d++;
-}
-g_print("\n");
-}
-#endif
-
-static inline gboolean
-osm_node_check_box(gdouble nlat, gdouble nlon)
-{
-if (use_bbox==FALSE)
- return TRUE;
-return (nlat > bbox.lat_min && nlat < bbox.lat_max && nlon > bbox.lon_min && nlon < bbox.lon_max) ? TRUE : FALSE;
-}
-
-static void
-osm_new_node_data(node *n)
-{
-if (n==NULL)
- return;
-if (n->data!=NULL)
- return;
-n->data=g_slice_new(node_data);
-n->data->name=NULL;
-n->data->url=NULL;
-n->data->desc=NULL;
-n->data->postal_code=NULL;
-n->type=NODE_PLAIN;
-noded_cnt++;
-}
-
-static void
-osm_free_node_data(node *n)
-{
-g_assert(n);
-g_assert(n->data);
-if (n->data->name)
- g_free(n->data->name);
-if (n->data->url)
- g_free(n->data->url);
-if (n->data->desc)
- g_free(n->data->desc);
-if (n->data->postal_code)
- g_free(n->data->postal_code);
-g_slice_free(node_data, n->data);
-n->data=NULL;
-noded_cnt--;
-}
-
-static node *
-osm_new_node(gint id, gdouble lat, gdouble lon)
-{
-node *n=NULL;
-
-n=g_slice_new(node);
-g_assert(n);
-n->id=id;
-n->lat=lat;
-n->lon=lon;
-n->data=(node_data *)NULL;
-return n;
-}
-
-static void
-osm_free_node(node *n)
-{
-g_assert(n);
-g_slice_free(node, n);
-}
-
-static node *
-osm_find_node(guint32 nid)
-{
-node *n;
-
-g_assert(osm_nodes);
-n=g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
-#if 0
-if (!n)
- g_printerr("ERROR: Node %d not found!\n", nid);
-#endif
-return n;
-}
-
-static void
-osm_new_way_data(way *w)
-{
-if (w==NULL)
- return;
-if (w->data!=NULL)
- return;
-
-w->data=g_slice_new(way_data);
-w->data->name=NULL;
-w->data->names=NULL;
-w->data->ref=NULL;
-w->data->int_ref=NULL;
-w->data->postal_code=NULL;
-w->data->layer=0;
-w->data->speed=0;
-}
-
-void
-osm_free_way_data(way *w)
-{
-g_assert(w);
-if (!w->data)
- return;
-if (w->data->name)
- g_free(w->data->name);
-if (w->data->ref)
- g_free(w->data->ref);
-if (w->data->int_ref)
- g_free(w->data->int_ref);
-g_slice_free(way_data, w->data);
-w->data=NULL;
-}
-
-static way *
-osm_new_way(gint id)
-{
-way *w;
-
-w=g_slice_new(way);
-g_assert(w);
-w->id=id;
-w->nodes=NULL;
-w->type=WAY_UNWAYED;
-w->data=NULL;
-w->ncnt=0;
-w->flags=0;
-
-/* Add to list of ways */
-return w;
-}
-
-static void
-osm_way_add_to_list(way *w)
-{
-g_assert(w);
-osm_ways=g_slist_prepend(osm_ways, w);
-}
-
-static void
-osm_way_new_node(way *w, gint nid)
-{
-node *n;
-
-g_assert(w);
-n=osm_find_node(nid);
-w->nodes=g_slist_prepend(w->nodes, n);
-w->ncnt++;
-}
-
-/**
- * Search the place hash table for the location of the node.
- *
- */
-static guint32
-osm_find_node_place(node *n)
-{
-node *t;
-gchar **isin;
-gchar **place;
-
-if (!n->data)
- return 0;
-
-isin=g_hash_table_lookup(osm_node_isin, GINT_TO_POINTER(n->id));
-
-if (!isin)
- return 0;
-
-place=isin;
-while (*place!=NULL) {
- gchar *ps;
- ps=g_strstrip(*place);
-#ifdef VERBOSE
- g_printf("Checking (%d) [%s] in [%s]\n",n->type, n->data->name, ps);
-#endif
- switch (n->type) {
- case NODE_PLACE_CITY:
- case NODE_PLACE_TOWN:
- case NODE_PLACE_VILLAGE:
- case NODE_PLACE_HAMLET:
- t=g_hash_table_lookup(osm_place_region, ps);
- if (t)
- return t->id;
- t=g_hash_table_lookup(osm_place_country, ps);
- if (t)
- return t->id;
- break;
- case NODE_PLACE_SUBURB:
- case NODE_PLACE_LOCALITY:
- t=g_hash_table_lookup(osm_place_city, ps);
- if (t)
- return t->id;
- break;
- case NODE_PLACE_ISLAND:
- return 0;
- break;
- default:
- t=g_hash_table_lookup(osm_place_city, ps);
- if (t)
- return t->id;
- break;
- }
- place++;
-}
-
-return 0;
-}
-
-guint32
-osm_find_way_place(way *w, node_type_t nt)
-{
-gchar **isin;
-gchar **place;
-
-isin=g_hash_table_lookup(osm_way_isin, GINT_TO_POINTER(w->id));
-if (!isin)
- return 0;
-
-place=isin;
-while (*place!=NULL) {
- node *t;
- gchar *ps;
-
- ps=g_strstrip(*place);
-
-#ifdef VERBOSE
- g_printf("Checking (%d) in [%s]\n",w->id, ps);
-#endif
-switch (nt) {
- case NODE_PLACE_CITY:
- case NODE_PLACE_TOWN:
- case NODE_PLACE_VILLAGE:
- case NODE_PLACE_HAMLET:
- case NODE_PLACE_LOCALITY:
- t=g_hash_table_lookup(osm_place_city, ps);
- if (t)
- return t->id;
- break;
- case NODE_PLACE_COUNTRY:
- t=g_hash_table_lookup(osm_place_country, ps);
- if (t)
- return t->id;
- break;
- default:
- g_assert_not_reached();
- break;
- }
- place++;
-}
-
-return 0;
-}
-
-/***********************************************************************/
-
-static void
-osm_node_save_node(gint key, gpointer value, gpointer user_data)
-{
-node *n=(node *)value;
-
-dbnode_cnt++;
-db_insert_node(n);
-if (dbnode_cnt % 26214==0)
- g_printf("\rNodes: %f%%\n",((float)dbnode_cnt/(float)node_cnt)*100);
-}
-
-/**
- * Check node type and insert as POI or Place
- * Discard extra data after insert.
- */
-static gboolean
-osm_node_save_poi(node *n, gpointer user_data)
-{
-if (!n) {
- g_printerr("ERROR: null poi\n");
- return FALSE;
-}
-
-if (!n->data) {
- g_printerr("POI node with no data ?\n");
- return FALSE;
-}
-
-n->data->isin_p=osm_find_node_place(n);
-n->data->isin_c=0;
-
-if (n->type>NODE_POI_START && n->type<NODE_POI_END) {
- print_node(n);
- db_insert_poi(n);
- osm_free_node_data(n);
-} else if (n->type>NODE_PLACE_START && n->type<NODE_PLACE_END) {
- print_node(n);
- db_insert_place(n);
-} else {
- osm_free_node_data(n);
- return FALSE;
-}
-
-return TRUE;
-}
-
-static gboolean
-osm_planet_poi_clear_nodes(void)
-{
-g_print("Removing old OSM POIs...\n");
-db_transaction_begin(db);
-sqlite3_step(sql.delete_osm_poi);
-sqlite3_step(sql.delete_place);
-return db_transaction_commit(db);
-}
-
-static gboolean
-osm_planet_poi_save_nodes(void)
-{
-g_print("Storing new POIs...\n");
-db_transaction_begin(db);
-g_slist_foreach(osm_poi, osm_node_save_poi, NULL);
-g_slist_free(osm_poi);
-return db_transaction_commit(db);
-}
-
-/*********************************************************************/
-
-static void
-osm_planet_clear_nodes(void)
-{
-g_print("Clearing old nodes\n");
-sqlite3_step(sql.delete_nodes);
-}
-
-static gboolean
-osm_planet_save_nodes(void)
-{
-g_print("Storing nodes\n");
-db_transaction_begin(db);
-g_hash_table_foreach(osm_nodes, osm_node_save_node, NULL);
-return db_transaction_commit(db);
-}
-
-/*********************************************************************/
-
-static void
-osm_way_save(way *value, gpointer user_data)
-{
-dbway_cnt++;
-db_insert_way(value);
-if (dbway_cnt % 16384==0 && dbway_cnt>0) {
- g_printf("\rWays: %f%%\n",(((float)dbway_cnt/(float)way_cnt)*100));
- print_way(value);
-}
-}
-
-static void
-osm_planet_clear_ways(void)
-{
-g_print("Clearing old data\n");
-sqlite3_step(sql.delete_way);
-sqlite3_step(sql.delete_way_name);
-sqlite3_step(sql.delete_way_ref);
-sqlite3_step(sql.delete_way_n2n);
-}
-
-static gboolean
-osm_planet_save_ways(void)
-{
-g_print("Inserting new ways\n");
-db_transaction_begin(db);
-g_slist_foreach(osm_ways, osm_way_save, NULL);
-return db_transaction_commit(db);
-}
-
-/*********************************************************************/
-
-static void
-osm_planet_save_all_nodes(void)
-{
-g_printf("Saving planet nodes to database:\n");
-
-osm_planet_poi_clear_nodes();
-osm_planet_poi_save_nodes();
-
-if (!is_update) {
- osm_planet_clear_nodes();
- osm_planet_clear_ways();
-}
-osm_planet_save_nodes();
-}
-
-static void
-osm_planet_save_all_ways(void)
-{
-g_printf("Saving planet way to database:\n");
-
-osm_planet_save_ways();
-}
-
-/***********************************************************************/
-
-static void
-_osm_tag_start(void *userData, const char *name, const char **atts)
-{
-tag_state_t t;
-gchar *k, *v;
-guint32 id, ndref;
-gdouble nlat, nlon;
-
-t=check_tag(name);
-switch (t) {
- case IN_OSM_TAG:
- g_printf("Starting...\n");
- break;
- case IN_NODE_TAG:
- tag_parent=IS_NODE;
- node_cnt++;
-
- id=atoi(get_attr_key_value(atts, "id"));
- nlat=atof(get_attr_key_value(atts, "lat"));
- nlon=atof(get_attr_key_value(atts, "lon"));
-
- cnode=osm_new_node(id, nlat, nlon);
- osm_node_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- break;
- case IN_WAY_TAG:
- tag_parent=IS_WAY;
- way_cnt++;
- id=atoi(get_attr_key_value(atts, "id"));
- cway=osm_new_way(id);
- osm_way_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- break;
- case IN_WNODE_TAG:
- ndref=atoi(get_attr_key_value(atts, "ref"));
- if (use_bbox==TRUE) {
- if (osm_find_node(ndref)==NULL) {
- cway->id=0;
- return;
- }
- }
- osm_way_new_node(cway, ndref);
- break;
- case IN_KEY_TAG:
- k=get_attr_key_value(atts, "k");
- if (strcmp(k,"created_by")==0)
- return;
- if (strcmp(k,"source")==0)
- return;
-
- v=get_attr_key_value(atts, "v");
-#ifdef VERBOSE_KEYS
- g_printf("TAG: K=[%s] V=[%s]\n", k, v);
-#endif
-
- switch (tag_parent) {
- case IS_NONE:
- g_printf("Tag key/value pair but unknown owner\n");
- break;
- case IS_NODE:
- {
- if (!osm_node_tags)
- return;
-
- /* Insert key/value pairs into hash table */
- if (cnode==NULL) {
- g_printerr("In node tags but node is NULL!\n");
- return;
- }
- g_hash_table_insert(osm_node_tags, g_strdup(k), g_strdup(v));
- }
- break;
- case IS_WAY:
- {
- if (cway==NULL) {
- g_printerr("In way tags but way is NULL!\n");
- return;
- }
- g_hash_table_insert(osm_way_tags, g_strdup(k), g_strdup(v));
- osm_new_way_data(cway);
- }
- break;
- case IS_RELATION:
-
- break;
- }
- break;
- case IN_BOUND_TAG:
- /* Ignore for now */
- g_printf("Ignoring bound tag\n");
- break;
- case IN_RELATION_TAG:
- tag_parent=IS_RELATION;
-
- break;
- case IN_MEMBER_TAG:
-
- break;
- default:
- tag_parent=IS_NONE;
- g_printf("Unknown tag: %s\n", name);
- break;
-}
-}
-
-static void
-_osm_tag_end(void *userData, const char *name)
-{
-tag_state_t t;
-gchar *v;
-guint i;
-t=check_tag(name);
-switch (t) {
- case IN_NODE_TAG:
-
- if (node_cnt % 262140==0) {
- g_printf("Nodes: %d of %d, POIs: %d, Outside box: %d\n", node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
- }
-
- if (!osm_node_tags)
- return;
-
- osm_new_node_data(cnode);
-
- for (i=0; nodeinfo[i].k; i++) {
- v=g_hash_table_lookup(osm_node_tags, nodeinfo[i].k);
- if (!v)
- continue;
- if (strcasecmp (v, nodeinfo[i].v)==0) {
- cnode->type=nodeinfo[i].type;
- break;
- }
- }
-
- /* Check if node is inside bounding box, if not skip it.
- * But keep it if it's something we might need for other nodes:
- * - Places (for is_in)
- * - ...
- */
- if ((osm_node_check_box(cnode->lat, cnode->lon)==FALSE) &&
- (cnode->type<NODE_PLACE_START)) {
- osm_free_node_data(cnode);
- osm_free_node(cnode);
- g_hash_table_destroy(osm_node_tags);
- node_skip_cnt++;
- return;
- }
-
- g_hash_table_insert(osm_nodes, GINT_TO_POINTER(cnode->id), cnode);
-
- if (cnode->type!=NODE_PLAIN) {
- cnode->data->name=NULL;
- v=g_hash_table_lookup(osm_node_tags, "name");
- if (v)
- cnode->data->name=g_strstrip(g_utf8_normalize(v, -1, G_NORMALIZE_ALL_COMPOSE));
- v=g_hash_table_lookup(osm_node_tags, "note");
- if (v)
- cnode->data->desc=g_strstrip(g_strdup(v));
- v=g_hash_table_lookup(osm_node_tags, "postal_code");
- if (v)
- cnode->data->postal_code=g_strstrip(g_strdup(v));
-
- /* Links */
- v=g_hash_table_lookup(osm_node_tags, "url");
- if (v) {
- cnode->data->url=g_strstrip(g_strdup(v));
- } else {
- v=g_hash_table_lookup(osm_node_tags, "wikipedia");
- if (v && strncmp(v,"http:", 5)==0)
- cnode->data->url=g_strstrip(g_strdup(v));
- }
- }
-
- cnode->data->isin_c=0;
- cnode->data->isin_p=0;
- v=g_hash_table_lookup(osm_node_tags, "is_in");
- if (v) {
- gchar **isin;
- isin=g_strsplit(v, ",", 10);
- g_hash_table_insert(osm_node_isin, GINT_TO_POINTER(cnode->id), isin);
- }
-
- if (cnode->type==NODE_PLAIN) {
- osm_free_node_data(cnode);
- } else {
- osm_poi=g_slist_prepend(osm_poi, cnode);
- if (cnode->data->name) {
- switch (cnode->type) {
- case NODE_PLACE_COUNTRY:
- g_hash_table_insert(osm_place_country, cnode->data->name, cnode);
- break;
- case NODE_PLACE_CITY:
- case NODE_PLACE_TOWN:
- g_hash_table_insert(osm_place_city, cnode->data->name, cnode);
- break;
- case NODE_PLACE_SUBURB:
- g_hash_table_insert(osm_place_suburb, cnode->data->name, cnode);
- break;
- case NODE_PLACE_VILLAGE:
- case NODE_PLACE_HAMLET:
- case NODE_PLACE_LOCALITY:
- g_hash_table_insert(osm_place_village, cnode->data->name, cnode);
- break;
- case NODE_PLACE_ISLAND:
- /* Ignore for now */
- break;
- default:;
- }
- }
- }
- g_hash_table_destroy(osm_node_tags);
- cnode=NULL;
- break;
- case IN_WAY_TAG:
- if (way_cnt % 1024==0) {
- g_printf("\rWays: %d\n", way_cnt);
- }
-
- cway->nodes=g_slist_reverse(cway->nodes);
-
- for (i=0; wayinfo[i].k; i++) {
- v=g_hash_table_lookup(osm_way_tags, wayinfo[i].k);
- if (!v)
- continue;
- if (strcasecmp (v, wayinfo[i].v)==0) {
- if (wayinfo[i].link==TRUE)
- cway->flags|=W_LINK;
- if (wayinfo[i].area==TRUE)
- cway->flags|=W_AREA;
- if (wayinfo[i].oneway==TRUE)
- cway->flags|=W_ONEWAY;
- cway->type=wayinfo[i].type;
- if (cway->data->speed==0)
- cway->data->speed=wayinfo[i].defspeed;
- break;
- }
- }
-
- v=g_hash_table_lookup(osm_way_tags, "name");
- if (v) {
- cway->data->name=g_utf8_normalize(v, -1, G_NORMALIZE_ALL_COMPOSE);
- /* Try to find other language names */
- cway->data->names=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_foreach(osm_way_tags, find_nls_names, cway->data->names);
- if (g_hash_table_size(cway->data->names)==0) {
- g_hash_table_destroy(cway->data->names);
- cway->data->names=NULL;
- }
- }
-
- v=g_hash_table_lookup(osm_way_tags, "ref");
- if (v)
- cway->data->ref=g_strdup(v);
- v=g_hash_table_lookup(osm_way_tags, "int_ref");
- if (v)
- cway->data->int_ref=g_strdup(v);
-
- v=g_hash_table_lookup(osm_way_tags, "postal_code");
- if (v)
- cway->data->postal_code=g_strdup(v);
-
- /* XXX: somehow handle the silly -1 'reversed' oneway */
- v=g_hash_table_lookup(osm_way_tags, "oneway");
- if (v)
- cway->flags|=W_ONEWAY;
-
- v=g_hash_table_lookup(osm_way_tags, "noexit");
- if (v)
- cway->flags|=W_NOEXIT;
-
- v=g_hash_table_lookup(osm_way_tags, "speedlimit");
- if (v)
- cway->data->speed=atoi(v);
- v=g_hash_table_lookup(osm_way_tags, "maxspeed");
- if (v)
- cway->data->speed=atoi(v);
-
-#if 0
- v=g_hash_table_lookup(osm_way_tags, "layer");
- if (v)
- cway->data->layer=atoi(v);
-#endif
-
- v=g_hash_table_lookup(osm_way_tags, "junction");
- if (v && strcasecmp(v,"roundabout")==0) {
- cway->flags|=W_ROUNDABOUT;
- cway->flags|=W_ONEWAY;
- } else if (v && strcasecmp(v,"mini_roundabout")==0) {
- cway->flags|=W_ROUNDABOUT;
- cway->flags|=W_ONEWAY;
- }
-
- /* XXX: Should check keys */
- v=g_hash_table_lookup(osm_way_tags, "access");
- if (v && (strcasecmp(v, "private")==0)) {
- cway->flags|=W_NOACCESS;
- }
-
- print_way(cway);
-
- v=g_hash_table_lookup(osm_way_tags, "is_in");
- if (v) {
- gchar **isin;
- isin=g_strsplit(v, ",", 10);
- g_hash_table_insert(osm_way_isin, GINT_TO_POINTER(cway->id), isin);
- }
-
- if (cway->data && cway->data->name==NULL && cway->data->ref==NULL &&
- cway->data->int_ref==NULL && cway->data->layer==0 && cway->data->speed==0)
- osm_free_way_data(cway);
-
- if (cway->id!=0)
- osm_way_add_to_list(cway);
-
- cway=NULL;
- g_hash_table_destroy(osm_way_tags);
- break;
- case IN_BOUND_TAG:
- /* */
- break;
- case IN_OSM_TAG:
- g_printf("\nPlanet loaded.\n");
- break;
- default:;
-}
-}
-
-/************************************************************************/
-
-static void
-storage_init(void)
-{
-osm_nodes=g_hash_table_new(g_direct_hash, g_direct_equal);
-
-osm_place_country=g_hash_table_new(g_str_hash, g_str_equal);
-osm_place_city=g_hash_table_new(g_str_hash, g_str_equal);
-osm_place_suburb=g_hash_table_new(g_str_hash, g_str_equal);
-osm_place_village=g_hash_table_new(g_str_hash, g_str_equal);
-osm_place_region=g_hash_table_new(g_str_hash, g_str_equal);
-osm_node_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
-osm_way_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
-}
-
-static void
-storage_free(void)
-{
-g_hash_table_destroy(osm_nodes);
-
-g_hash_table_destroy(osm_place_country);
-g_hash_table_destroy(osm_place_city);
-g_hash_table_destroy(osm_place_suburb);
-g_hash_table_destroy(osm_place_village);
-g_hash_table_destroy(osm_place_region);
-g_hash_table_destroy(osm_node_isin);
-}
-
-void
-osm_planet_parser_init(void)
-{
-xp=XML_ParserCreate(NULL);
-XML_SetElementHandler(xp, _osm_tag_start, _osm_tag_end);
-storage_init();
-}
-
-void
-osm_planet_parser_deinit(void)
-{
-XML_ParserFree(xp);
-storage_free();
-}
-
-gboolean
-osm_planet_parse_buffer(gchar *buffer, size_t r)
-{
-if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) {
- g_printerr("Parse error at line %d:\n%s\n",
- XML_GetCurrentLineNumber(xp),
- XML_ErrorString(XML_GetErrorCode(xp)));
- return FALSE;
-}
-return TRUE;
-}
-
-gboolean
-osm_planet_parse_file(gchar *pfile)
-{
-FILE *f;
-BZFILE *b;
-int bzerror;
-int r;
-gchar buffer[FILE_BUFFER];
-gboolean res=TRUE;
-
-f=fopen(pfile, "r");
-if (!f) {
- perror("fopen failed\n");
- return FALSE;
-}
-
-b=BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
-if (bzerror != BZ_OK) {
- g_printf("BZ2_bzReadOpen failed\n");
- BZ2_bzReadClose(&bzerror, b);
- return FALSE;
-}
-
-do {
- r=BZ2_bzRead(&bzerror, b, buffer, FILE_BUFFER);
- if ((bzerror!=BZ_STREAM_END) && (bzerror!=BZ_OK)) {
- res=FALSE;
- break;
- }
- if (!osm_planet_parse_buffer(buffer, r)) {
- res=FALSE;
- break;
- }
-} while (bzerror==BZ_OK);
-
-BZ2_bzReadClose(&bzerror, b);
-fclose(f);
-return res;
-}
-
-/************************************************************************/
-
static gint
print_fail(const gchar *msg, gint ret)
{
return ret;
}
-/************************************************************************/
-
-static void
-print_memory_usage(void)
-{
-g_print("Memory usage per item:\n");
-g_printf("Node size: %d\n", (gint)sizeof(node));
-g_printf("NodeD size: %d\n", (gint)sizeof(node_data));
-g_printf("Way size: %d\n", (gint)sizeof(way));
-g_printf("WayD size: %d\n", (gint)sizeof(way_data));
-}
-
-/************************************************************************/
-
int main (int argc, char **argv)
{
gchar *in_file;
gchar *out_file;
-if (argc<2) {
+if (argc<2)
return print_fail("Give bzip2 compressed planet XML file as argument", 1);
-}
out_file=OSM_DB_FILE;
in_file=argv[1];
g_printf("Using file: %s\n", in_file);
if (argc==6) {
- use_bbox=TRUE;
- bbox.lat_min=atof(argv[2]);
- bbox.lon_min=atof(argv[3]);
- bbox.lat_max=atof(argv[4]);
- bbox.lon_max=atof(argv[5]);
- g_printf("Skipping data outside of box: %f,%f - %f,%f\n",
- bbox.lat_min, bbox.lon_min,
- bbox.lat_max, bbox.lon_max);
- g_print("Note: missing nodes can't be reported.\n");
-} else use_bbox=FALSE;
-
-if (db_connect(&db, out_file)!=TRUE)
- return print_fail("Database open failed", 2);
-
-db_create_tables(db);
-db_create_indexes(db);
-db_prepare(db);
-
-print_memory_usage();
-
-osm_planet_parser_init();
-if (osm_planet_parse_file(argv[1])==FALSE) {
- g_printf("Failed to parse file: %s\n", in_file);
- return 1;
+ osm_import_set_bbox(TRUE, atof(argv[2]), atof(argv[3]), atof(argv[4]), atof(argv[5]));
+} else {
+ osm_import_set_bbox(FALSE, 0, 0, 0, 0);
}
-g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt);
-g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
-g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
-g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
-g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes));
-
-osm_planet_save_all_nodes();
-osm_planet_save_all_ways();
-osm_planet_parser_deinit();
-db_close(&db);
-
-g_printf("Named ways: %d, Numbered ways: %d\n", way_names, way_refs);
-
+if (osm_import(in_file, out_file)==FALSE) {
+ return print_fail("Import failed", 4);
+}
return 0;
}