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