Diff of /trunk/src/osm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 6 by achadwick, Thu Dec 11 13:26:13 2008 UTC revision 28 by achadwick, Wed Dec 24 14:17:20 2008 UTC
# Line 17  Line 17 
17   * along with OSM2Go.  If not, see <http://www.gnu.org/licenses/>.   * along with OSM2Go.  If not, see <http://www.gnu.org/licenses/>.
18   */   */
19    
20    #define OSM_STREAM_PARSER
21    
22  #include <stdio.h>  #include <stdio.h>
23  #include <stdlib.h>  #include <stdlib.h>
24  #include <string.h>  #include <string.h>
# Line 29  Line 31 
31  #include <libxml/tree.h>  #include <libxml/tree.h>
32    
33  #include "appdata.h"  #include "appdata.h"
34    #include "banner.h"
35    
36  #ifndef LIBXML_TREE_ENABLED  #ifndef LIBXML_TREE_ENABLED
37  #error "Tree not enabled in libxml"  #error "Tree not enabled in libxml"
# Line 40  Line 43 
43  #define OSM_SORT_LAST  #define OSM_SORT_LAST
44  // #define OSM_SORT_FIRST  // #define OSM_SORT_FIRST
45    
46  /* ------------------------- user handling --------------------- */  /* ------------------------- bounds handling --------------------- */
47    
48  static void osm_bounds_free(bounds_t *bounds) {  static void osm_bounds_free(bounds_t *bounds) {
49    free(bounds);    free(bounds);
# Line 52  static void osm_bounds_dump(bounds_t *bo Line 55  static void osm_bounds_dump(bounds_t *bo
55           bounds->ll_min.lon, bounds->ll_max.lon);           bounds->ll_min.lon, bounds->ll_max.lon);
56  }  }
57    
58    #ifndef OSM_STREAM_PARSER
59  static bounds_t *osm_parse_osm_bounds(osm_t *osm,  static bounds_t *osm_parse_osm_bounds(osm_t *osm,
60                       xmlDocPtr doc, xmlNode *a_node) {                       xmlDocPtr doc, xmlNode *a_node) {
61    char *prop;    char *prop;
# Line 92  static bounds_t *osm_parse_osm_bounds(os Line 96  static bounds_t *osm_parse_osm_bounds(os
96             bounds->ll_min.lat, bounds->ll_min.lon,             bounds->ll_min.lat, bounds->ll_min.lon,
97             bounds->ll_max.lat, bounds->ll_max.lon);             bounds->ll_max.lat, bounds->ll_max.lon);
98    
99      g_free(bounds);      osm_bounds_free(bounds);
100      return NULL;      return NULL;
101    }    }
102    
# Line 122  static bounds_t *osm_parse_osm_bounds(os Line 126  static bounds_t *osm_parse_osm_bounds(os
126    
127    return bounds;    return bounds;
128  }  }
129    #endif
130    
131  /* ------------------------- user handling --------------------- */  /* ------------------------- user handling --------------------- */
132    
# Line 319  void osm_nodes_dump(node_t *node) { Line 324  void osm_nodes_dump(node_t *node) {
324    }    }
325  }  }
326    
327    #ifndef OSM_STREAM_PARSER
328  static node_t *osm_parse_osm_node(osm_t *osm,  static node_t *osm_parse_osm_node(osm_t *osm,
329                            xmlDocPtr doc, xmlNode *a_node) {                            xmlDocPtr doc, xmlNode *a_node) {
330    xmlNode *cur_node = NULL;    xmlNode *cur_node = NULL;
# Line 375  static node_t *osm_parse_osm_node(osm_t Line 381  static node_t *osm_parse_osm_node(osm_t
381    
382    return node;    return node;
383  }  }
384    #endif
385    
386  /* ------------------- way handling ------------------- */  /* ------------------- way handling ------------------- */
387    
# Line 485  node_chain_t *osm_parse_osm_way_nd(osm_t Line 492  node_chain_t *osm_parse_osm_way_nd(osm_t
492    return NULL;    return NULL;
493  }  }
494    
495    #ifndef OSM_STREAM_PARSER
496  static way_t *osm_parse_osm_way(osm_t *osm,  static way_t *osm_parse_osm_way(osm_t *osm,
497                            xmlDocPtr doc, xmlNode *a_node) {                            xmlDocPtr doc, xmlNode *a_node) {
498    xmlNode *cur_node = NULL;    xmlNode *cur_node = NULL;
# Line 534  static way_t *osm_parse_osm_way(osm_t *o Line 542  static way_t *osm_parse_osm_way(osm_t *o
542    
543    return way;    return way;
544  }  }
545    #endif
546    
547  /* ------------------- relation handling ------------------- */  /* ------------------- relation handling ------------------- */
548    
# Line 688  member_t *osm_parse_osm_relation_member( Line 697  member_t *osm_parse_osm_relation_member(
697    return member;    return member;
698  }  }
699    
700    #ifndef OSM_STREAM_PARSER
701  static relation_t *osm_parse_osm_relation(osm_t *osm,  static relation_t *osm_parse_osm_relation(osm_t *osm,
702                            xmlDocPtr doc, xmlNode *a_node) {                            xmlDocPtr doc, xmlNode *a_node) {
703    xmlNode *cur_node = NULL;    xmlNode *cur_node = NULL;
# Line 854  static osm_t *osm_parse_doc(xmlDocPtr do Line 864  static osm_t *osm_parse_doc(xmlDocPtr do
864    
865    return osm;    return osm;
866  }  }
867    #endif
868    
869  /* ------------------ osm handling ----------------- */  /* ------------------ osm handling ----------------- */
870    
# Line 876  void osm_dump(osm_t *osm) { Line 887  void osm_dump(osm_t *osm) {
887    osm_relations_dump(osm->relation);    osm_relations_dump(osm->relation);
888  }  }
889    
890    #ifdef OSM_STREAM_PARSER
891    /* -------------------------- stream parser tests ------------------- */
892    
893    #include <libxml/xmlreader.h>
894    
895    static gint my_strcmp(const xmlChar *a, const xmlChar *b) {
896      if(!a && !b) return 0;
897      if(!a) return -1;
898      if(!b) return +1;
899      return strcmp((char*)a,(char*)b);
900    }
901    
902    /* skip current element incl. everything below (mainly for testing) */
903    /* returns FALSE if something failed */
904    static gboolean skip_element(xmlTextReaderPtr reader) {
905      g_assert(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT);
906      const xmlChar *name = xmlTextReaderConstName(reader);
907      g_assert(name);
908      int depth = xmlTextReaderDepth(reader);
909    
910      if(xmlTextReaderIsEmptyElement(reader))
911        return TRUE;
912    
913      int ret = xmlTextReaderRead(reader);
914      while((ret == 1) &&
915            ((xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) ||
916             (xmlTextReaderDepth(reader) > depth) ||
917             (my_strcmp(xmlTextReaderConstName(reader), name) != 0))) {
918        ret = xmlTextReaderRead(reader);
919      }
920      return(ret == 1);
921    }
922    
923    /* parse bounds */
924    static bounds_t *process_bounds(xmlTextReaderPtr reader) {
925      char *prop = NULL;
926      bounds_t *bounds = g_new0(bounds_t, 1);
927    
928      bounds->ll_min.lat = bounds->ll_min.lon = NAN;
929      bounds->ll_max.lat = bounds->ll_max.lon = NAN;
930    
931      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "minlat"))) {
932        bounds->ll_min.lat = g_ascii_strtod(prop, NULL);
933        xmlFree(prop);
934      }
935    
936      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "maxlat"))) {
937        bounds->ll_max.lat = g_ascii_strtod(prop, NULL);
938        xmlFree(prop);
939      }
940    
941      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "minlon"))) {
942        bounds->ll_min.lon = g_ascii_strtod(prop, NULL);
943        xmlFree(prop);
944      }
945    
946      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "maxlon"))) {
947        bounds->ll_max.lon = g_ascii_strtod(prop, NULL);
948        xmlFree(prop);
949      }
950    
951      if(isnan(bounds->ll_min.lat) || isnan(bounds->ll_min.lon) ||
952         isnan(bounds->ll_max.lat) || isnan(bounds->ll_max.lon)) {
953        errorf(NULL, "Invalid coordinate in bounds (%f/%f/%f/%f)",
954               bounds->ll_min.lat, bounds->ll_min.lon,
955               bounds->ll_max.lat, bounds->ll_max.lon);
956    
957        osm_bounds_free(bounds);
958        return NULL;
959      }
960    
961      /* skip everything below */
962      skip_element(reader);
963    
964      /* calculate map zone which will be used as a reference for all */
965      /* drawing/projection later on */
966      pos_t center = { (bounds->ll_max.lat + bounds->ll_min.lat)/2,
967                       (bounds->ll_max.lon + bounds->ll_min.lon)/2 };
968    
969      pos2lpos_center(&center, &bounds->center);
970    
971      /* the scale is needed to accomodate for "streching" */
972      /* by the mercartor projection */
973      bounds->scale = cos(DEG2RAD(center.lat));
974    
975      pos2lpos_center(&bounds->ll_min, &bounds->min);
976      bounds->min.x -= bounds->center.x;
977      bounds->min.y -= bounds->center.y;
978      bounds->min.x *= bounds->scale;
979      bounds->min.y *= bounds->scale;
980    
981      pos2lpos_center(&bounds->ll_max, &bounds->max);
982      bounds->max.x -= bounds->center.x;
983      bounds->max.y -= bounds->center.y;
984      bounds->max.x *= bounds->scale;
985      bounds->max.y *= bounds->scale;
986    
987      return bounds;
988    }
989    
990    static tag_t *process_tag(xmlTextReaderPtr reader) {
991      /* allocate a new tag structure */
992      tag_t *tag = g_new0(tag_t, 1);
993    
994      char *prop;
995      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "k"))) {
996        if(strlen(prop) > 0) tag->key = g_strdup(prop);
997        xmlFree(prop);
998      }
999    
1000      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "v"))) {
1001        if(strlen(prop) > 0) tag->value = g_strdup(prop);
1002        xmlFree(prop);
1003      }
1004    
1005      if(!tag->key || !tag->value) {
1006        printf("incomplete tag key/value %s/%s\n", tag->key, tag->value);
1007        osm_tags_free(tag);
1008        tag = NULL;
1009      }
1010    
1011      skip_element(reader);
1012      return tag;
1013    }
1014    
1015    static node_t *process_node(xmlTextReaderPtr reader, osm_t *osm) {
1016    
1017      /* allocate a new node structure */
1018      node_t *node = g_new0(node_t, 1);
1019      node->pos.lat = node->pos.lon = NAN;
1020    
1021      char *prop;
1022      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "id"))) {
1023        node->id = strtoul(prop, NULL, 10);
1024        xmlFree(prop);
1025      }
1026    
1027      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "lat"))) {
1028        node->pos.lat = g_ascii_strtod(prop, NULL);
1029        xmlFree(prop);
1030      }
1031    
1032      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "lon"))) {
1033        node->pos.lon = g_ascii_strtod(prop, NULL);
1034        xmlFree(prop);
1035      }
1036    
1037      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {
1038        node->user = osm_user(osm, prop);
1039        xmlFree(prop);
1040      }
1041    
1042      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "visible"))) {
1043        node->visible = (strcasecmp(prop, "true") == 0);
1044        xmlFree(prop);
1045      }
1046    
1047      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "timestamp"))) {
1048        node->time = convert_iso8601(prop);
1049        xmlFree(prop);
1050      }
1051    
1052      pos2lpos(osm->bounds, &node->pos, &node->lpos);
1053    
1054      /* just an empty element? then return the node as it is */
1055      if(xmlTextReaderIsEmptyElement(reader))
1056        return node;
1057    
1058      /* parse tags if present */
1059      int depth = xmlTextReaderDepth(reader);
1060    
1061      /* scan all elements on same level or its children */
1062      tag_t **tag = &node->tag;
1063      int ret = xmlTextReaderRead(reader);
1064      while((ret == 1) &&
1065            ((xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) ||
1066             (xmlTextReaderDepth(reader) != depth))) {
1067    
1068        if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
1069          char *subname = (char*)xmlTextReaderConstName(reader);
1070          if(strcasecmp(subname, "tag") == 0) {
1071            *tag = process_tag(reader);
1072            if(*tag) tag = &(*tag)->next;
1073          } else
1074            skip_element(reader);
1075        }
1076    
1077        ret = xmlTextReaderRead(reader);
1078      }
1079    
1080      return node;
1081    }
1082    
1083    static node_chain_t *process_nd(xmlTextReaderPtr reader, osm_t *osm) {
1084      char *prop;
1085    
1086      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "ref"))) {
1087        item_id_t id = strtoul(prop, NULL, 10);
1088        node_chain_t *node_chain = g_new0(node_chain_t, 1);
1089    
1090        /* search matching node */
1091        node_chain->node = osm->node;
1092        while(node_chain->node && node_chain->node->id != id)
1093          node_chain->node = node_chain->node->next;
1094    
1095        if(!node_chain->node) printf("Node id %lu not found\n", id);
1096    
1097        if(node_chain->node)
1098          node_chain->node->ways++;
1099    
1100        xmlFree(prop);
1101    
1102        skip_element(reader);
1103        return node_chain;
1104      }
1105    
1106      skip_element(reader);
1107      return NULL;
1108    }
1109    
1110    static way_t *process_way(xmlTextReaderPtr reader, osm_t *osm) {
1111      /* allocate a new way structure */
1112      way_t *way = g_new0(way_t, 1);
1113    
1114      char *prop;
1115      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "id"))) {
1116        way->id = strtoul(prop, NULL, 10);
1117        xmlFree(prop);
1118      }
1119    
1120      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {
1121        way->user = osm_user(osm, prop);
1122        xmlFree(prop);
1123      }
1124    
1125      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "visible"))) {
1126        way->visible = (strcasecmp(prop, "true") == 0);
1127        xmlFree(prop);
1128      }
1129    
1130      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "timestamp"))) {
1131        way->time = convert_iso8601(prop);
1132        xmlFree(prop);
1133      }
1134    
1135      /* just an empty element? then return the way as it is */
1136      /* (this should in fact never happen as this would be a way without nodes) */
1137      if(xmlTextReaderIsEmptyElement(reader))
1138        return way;
1139    
1140      /* parse tags/nodes if present */
1141      int depth = xmlTextReaderDepth(reader);
1142    
1143      /* scan all elements on same level or its children */
1144      tag_t **tag = &way->tag;
1145      node_chain_t **node_chain = &way->node_chain;
1146      int ret = xmlTextReaderRead(reader);
1147      while((ret == 1) &&
1148            ((xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) ||
1149             (xmlTextReaderDepth(reader) != depth))) {
1150    
1151        if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
1152          char *subname = (char*)xmlTextReaderConstName(reader);
1153          if(strcasecmp(subname, "nd") == 0) {
1154            *node_chain = process_nd(reader, osm);
1155            if(*node_chain) node_chain = &(*node_chain)->next;
1156          } else if(strcasecmp(subname, "tag") == 0) {
1157            *tag = process_tag(reader);
1158            if(*tag) tag = &(*tag)->next;
1159          } else
1160            skip_element(reader);
1161        }
1162        ret = xmlTextReaderRead(reader);
1163      }
1164    
1165      return way;
1166    }
1167    
1168    static member_t *process_member(xmlTextReaderPtr reader, osm_t *osm) {
1169      char *prop;
1170      member_t *member = g_new0(member_t, 1);
1171      member->type = ILLEGAL;
1172    
1173      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "type"))) {
1174        if(strcasecmp(prop, "way") == 0)           member->type = WAY;
1175        else if(strcasecmp(prop, "node") == 0)     member->type = NODE;
1176        else if(strcasecmp(prop, "relation") == 0) member->type = RELATION;
1177        xmlFree(prop);
1178      }
1179    
1180      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "ref"))) {
1181        item_id_t id = strtoul(prop, NULL, 10);
1182    
1183        switch(member->type) {
1184        case ILLEGAL:
1185          printf("Unable to store illegal type\n");
1186          break;
1187    
1188        case WAY:
1189          /* search matching way */
1190          member->way = osm->way;
1191          while(member->way && member->way->id != id)
1192            member->way = member->way->next;
1193    
1194          if(!member->way) {
1195            member->type = WAY_ID;
1196            member->id = id;
1197          }
1198          break;
1199    
1200        case NODE:
1201          /* search matching node */
1202          member->node = osm->node;
1203          while(member->node && member->node->id != id)
1204            member->node = member->node->next;
1205    
1206          if(!member->node) {
1207            member->type = NODE_ID;
1208            member->id = id;
1209          }
1210          break;
1211    
1212        case RELATION:
1213          /* search matching relation */
1214          member->relation = osm->relation;
1215          while(member->relation && member->relation->id != id)
1216            member->relation = member->relation->next;
1217    
1218          if(!member->relation) {
1219            member->type = NODE_ID;
1220            member->id = id;
1221          }
1222          break;
1223    
1224        case WAY_ID:
1225        case NODE_ID:
1226        case RELATION_ID:
1227          break;
1228        }
1229    
1230        xmlFree(prop);
1231      }
1232    
1233      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "role"))) {
1234        if(strlen(prop) > 0) member->role = g_strdup(prop);
1235        xmlFree(prop);
1236      }
1237    
1238      return member;
1239    }
1240    
1241    static relation_t *process_relation(xmlTextReaderPtr reader, osm_t *osm) {
1242      /* allocate a new relation structure */
1243      relation_t *relation = g_new0(relation_t, 1);
1244    
1245      char *prop;
1246      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "id"))) {
1247        relation->id = strtoul(prop, NULL, 10);
1248        xmlFree(prop);
1249      }
1250    
1251      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {
1252        relation->user = osm_user(osm, prop);
1253        xmlFree(prop);
1254      }
1255    
1256      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "visible"))) {
1257        relation->visible = (strcasecmp(prop, "true") == 0);
1258        xmlFree(prop);
1259      }
1260    
1261      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "timestamp"))) {
1262        relation->time = convert_iso8601(prop);
1263        xmlFree(prop);
1264      }
1265    
1266      /* just an empty element? then return the relation as it is */
1267      /* (this should in fact never happen as this would be a relation */
1268      /* without members) */
1269      if(xmlTextReaderIsEmptyElement(reader))
1270        return relation;
1271    
1272      /* parse tags/member if present */
1273      int depth = xmlTextReaderDepth(reader);
1274    
1275      /* scan all elements on same level or its children */
1276      tag_t **tag = &relation->tag;
1277      member_t **member = &relation->member;
1278      int ret = xmlTextReaderRead(reader);
1279      while((ret == 1) &&
1280            ((xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) ||
1281             (xmlTextReaderDepth(reader) != depth))) {
1282    
1283        if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
1284          char *subname = (char*)xmlTextReaderConstName(reader);
1285          if(strcasecmp(subname, "nd") == 0) {
1286            *member = process_member(reader, osm);
1287            if(*member) member = &(*member)->next;
1288          } else if(strcasecmp(subname, "tag") == 0) {
1289            *tag = process_tag(reader);
1290            if(*tag) tag = &(*tag)->next;
1291          } else
1292            skip_element(reader);
1293        }
1294        ret = xmlTextReaderRead(reader);
1295      }
1296    
1297      return relation;
1298    }
1299    
1300    static osm_t *process_osm(xmlTextReaderPtr reader) {
1301      /* alloc osm structure */
1302      osm_t *osm = g_new0(osm_t, 1);
1303    
1304      node_t **node = &osm->node;
1305      way_t **way = &osm->way;
1306      relation_t **relation = &osm->relation;
1307    
1308      /* no attributes of interest */
1309    
1310      const xmlChar *name = xmlTextReaderConstName(reader);
1311      g_assert(name);
1312    
1313      /* read next node */
1314      int num_elems = 0;
1315      const int tick_every = 50; // Balance responsive appearance with performance.
1316      int ret = xmlTextReaderRead(reader);
1317      while(ret == 1) {
1318    
1319        switch(xmlTextReaderNodeType(reader)) {
1320        case XML_READER_TYPE_ELEMENT:
1321    
1322          g_assert(xmlTextReaderDepth(reader) == 1);
1323          char *name = (char*)xmlTextReaderConstName(reader);
1324          if(strcasecmp(name, "bounds") == 0) {
1325            osm->bounds = process_bounds(reader);
1326          } else if(strcasecmp(name, "node") == 0) {
1327            *node = process_node(reader, osm);
1328            if(*node) node = &(*node)->next;
1329          } else if(strcasecmp(name, "way") == 0) {
1330            *way = process_way(reader, osm);
1331            if(*way) way = &(*way)->next;
1332          } else if(strcasecmp(name, "relation") == 0) {
1333            *relation = process_relation(reader, osm);
1334            if(*relation) relation = &(*relation)->next;
1335          } else {
1336            printf("something unknown found\n");
1337            g_assert(0);
1338            skip_element(reader);
1339          }
1340          break;
1341    
1342        case XML_READER_TYPE_END_ELEMENT:
1343          /* end element must be for the current element */
1344          g_assert(xmlTextReaderDepth(reader) == 0);
1345          return osm;
1346          break;
1347    
1348        default:
1349          break;
1350        }
1351        ret = xmlTextReaderRead(reader);
1352    
1353        if (num_elems++ > tick_every) {
1354          num_elems = 0;
1355          banner_busy_tick();
1356        }
1357      }
1358    
1359      g_assert(0);
1360      return NULL;
1361    }
1362    
1363    static osm_t *process_file(const char *filename) {
1364      osm_t *osm = NULL;
1365      xmlTextReaderPtr reader;
1366      int ret;
1367    
1368      reader = xmlReaderForFile(filename, NULL, 0);
1369      if (reader != NULL) {
1370        ret = xmlTextReaderRead(reader);
1371        if(ret == 1) {
1372          char *name = (char*)xmlTextReaderConstName(reader);
1373          if(name && strcasecmp(name, "osm") == 0)
1374            osm = process_osm(reader);
1375        } else
1376          printf("file empty\n");
1377    
1378        xmlFreeTextReader(reader);
1379      } else {
1380        fprintf(stderr, "Unable to open %s\n", filename);
1381      }
1382      return osm;
1383    }
1384    
1385    /* ----------------------- end of stream parser tests ------------------- */
1386    #endif
1387    
1388    #include <sys/time.h>
1389    
1390  osm_t *osm_parse(char *filename) {  osm_t *osm_parse(char *filename) {
1391    xmlDoc *doc = NULL;  
1392      struct timeval start;
1393      gettimeofday(&start, NULL);
1394    
1395    LIBXML_TEST_VERSION;    LIBXML_TEST_VERSION;
1396    
1397    #ifdef OSM_STREAM_PARSER
1398      // use stream parser
1399      osm_t *osm = process_file(filename);
1400      xmlCleanupParser();
1401    
1402    #else
1403      // parse into a tree
1404    /* parse the file and get the DOM */    /* parse the file and get the DOM */
1405      xmlDoc *doc = NULL;
1406    if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {    if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {
1407      xmlErrorPtr errP = xmlGetLastError();      xmlErrorPtr errP = xmlGetLastError();
1408      errorf(NULL, "While parsing \"%s\":\n\n%s", filename, errP->message);      errorf(NULL, "While parsing \"%s\":\n\n%s", filename, errP->message);
1409      return NULL;      return NULL;
1410    }    }
1411    
1412    return osm_parse_doc(doc);    osm_t *osm = osm_parse_doc(doc);
1413    #endif
1414    
1415      struct timeval end;
1416      gettimeofday(&end, NULL);
1417    
1418      printf("total parse time: %ldms\n",
1419             (end.tv_usec - start.tv_usec)/1000 +
1420             (end.tv_sec - start.tv_sec)*1000);
1421    
1422      return osm;
1423  }  }
1424    
1425  gboolean osm_sanity_check(GtkWidget *parent, osm_t *osm) {  gboolean osm_sanity_check(GtkWidget *parent, osm_t *osm) {
# Line 1468  way_chain_t *osm_node_to_way(osm_t *osm, Line 1999  way_chain_t *osm_node_to_way(osm_t *osm,
1999        cur_chain = &((*cur_chain)->next);        cur_chain = &((*cur_chain)->next);
2000      }      }
2001    
2002      way = way->next;       way = way->next;
2003    }    }
2004    
2005    return chain;    return chain;
# Line 1669  tag_t *osm_tags_copy(tag_t *src_tag, gbo Line 2200  tag_t *osm_tags_copy(tag_t *src_tag, gbo
2200    
2201    return new_tags;    return new_tags;
2202  }  }
2203    // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.6  
changed lines
  Added in v.28