Diff of /trunk/src/osm.c

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

revision 98 by achadwick, Sun Feb 22 03:41:09 2009 UTC revision 161 by harbaum, Sat Apr 11 11:28:56 2009 UTC
# Line 35  Line 35 
35  #error "Tree not enabled in libxml"  #error "Tree not enabled in libxml"
36  #endif  #endif
37    
 /* determine where a node/way/relation read from the osm file */  
 /* is inserted into the internal database */  
 // #define OSM_SORT_ID  
 #define OSM_SORT_LAST  
 // #define OSM_SORT_FIRST  
   
38  /* ------------------------- bounds handling --------------------- */  /* ------------------------- bounds handling --------------------- */
39    
40  static void osm_bounds_free(bounds_t *bounds) {  static void osm_bounds_free(bounds_t *bounds) {
# Line 233  void osm_node_dump(node_t *node) { Line 227  void osm_node_dump(node_t *node) {
227    char buf[64];    char buf[64];
228    struct tm tm;    struct tm tm;
229    
230    printf("Id:      %lu\n", node->id);    printf("Id:      "ITEM_ID_FORMAT"\n", node->id);
231    printf("User:    %s\n", node->user?node->user->name:"<unspecified>");    printf("User:    %s\n", node->user?node->user->name:"<unspecified>");
232    printf("Visible: %s\n", node->visible?"yes":"no");    printf("Visible: %s\n", node->visible?"yes":"no");
233    
# Line 266  void osm_node_chain_free(node_chain_t *n Line 260  void osm_node_chain_free(node_chain_t *n
260  }  }
261    
262  void osm_way_free(way_t *way) {  void osm_way_free(way_t *way) {
263    //  printf("freeing way #%ld\n", way->id);    //  printf("freeing way #" ITEM_ID_FORMAT "\n", way->id);
264    
265    osm_node_chain_free(way->node_chain);    osm_node_chain_free(way->node_chain);
266    osm_tags_free(way->tag);    osm_tags_free(way->tag);
# Line 311  void osm_way_dump(way_t *way) { Line 305  void osm_way_dump(way_t *way) {
305    char buf[64];    char buf[64];
306    struct tm tm;    struct tm tm;
307    
308    printf("Id:      %lu\n", way->id);    printf("Id:      "ITEM_ID_FORMAT"\n", way->id);
309    printf("User:    %s\n", way->user?way->user->name:"<unspecified>");    printf("User:    %s\n", way->user?way->user->name:"<unspecified>");
310    printf("Visible: %s\n", way->visible?"yes":"no");    printf("Visible: %s\n", way->visible?"yes":"no");
311    node_chain_t *node_chain = way->node_chain;    node_chain_t *node_chain = way->node_chain;
312    while(node_chain) {    while(node_chain) {
313      printf("  Node:  %lu\n", node_chain->node->id);      printf("  Node:  "ITEM_ID_FORMAT"\n", node_chain->node->id);
314      node_chain = node_chain->next;      node_chain = node_chain->next;
315    }    }
316    
# Line 345  node_chain_t *osm_parse_osm_way_nd(osm_t Line 339  node_chain_t *osm_parse_osm_way_nd(osm_t
339    
340      /* search matching node */      /* search matching node */
341      node_chain->node = osm_get_node_by_id(osm, id);      node_chain->node = osm_get_node_by_id(osm, id);
342      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id " ITEM_ID_FORMAT " not found\n", id);
343      else                  node_chain->node->ways++;      else                  node_chain->node->ways++;
344    
345      xmlFree(prop);      xmlFree(prop);
# Line 392  void osm_relations_dump(relation_t *rela Line 386  void osm_relations_dump(relation_t *rela
386      char buf[64];      char buf[64];
387      struct tm tm;      struct tm tm;
388    
389      printf("Id:      %lu\n", relation->id);      printf("Id:      "ITEM_ID_FORMAT"\n", relation->id);
390      printf("User:    %s\n",      printf("User:    %s\n",
391             relation->user?relation->user->name:"<unspecified>");             relation->user?relation->user->name:"<unspecified>");
392      printf("Visible: %s\n", relation->visible?"yes":"no");      printf("Visible: %s\n", relation->visible?"yes":"no");
393    
394      member_t *member = relation->member;      member_t *member = relation->member;
395      while(member) {      while(member) {
396        switch(member->type) {        switch(member->object.type) {
397        case ILLEGAL:        case ILLEGAL:
398        case NODE_ID:        case NODE_ID:
399        case WAY_ID:        case WAY_ID:
# Line 407  void osm_relations_dump(relation_t *rela Line 401  void osm_relations_dump(relation_t *rela
401          break;          break;
402    
403        case NODE:        case NODE:
404          if(member->node)          if(member->object.node)
405            printf(" Member: Node, id = %lu, role = %s\n",            printf(" Member: Node, id = " ITEM_ID_FORMAT ", role = %s\n",
406                   member->node->id, member->role);                   member->object.node->id, member->role);
407          break;          break;
408    
409        case WAY:        case WAY:
410          if(member->way)          if(member->object.way)
411          printf(" Member: Way, id = %lu, role = %s\n",            printf(" Member: Way, id = " ITEM_ID_FORMAT ", role = %s\n",
412                 member->way->id, member->role);                   member->object.way->id, member->role);
413          break;          break;
414    
415        case RELATION:        case RELATION:
416          if(member->relation)          if(member->object.relation)
417          printf(" Member: Relation, id = %lu, role = %s\n",            printf(" Member: Relation, id = " ITEM_ID_FORMAT ", role = %s\n",
418                 member->relation->id, member->role);                   member->object.relation->id, member->role);
419          break;          break;
420        }        }
421    
# Line 442  member_t *osm_parse_osm_relation_member( Line 436  member_t *osm_parse_osm_relation_member(
436                            xmlDocPtr doc, xmlNode *a_node) {                            xmlDocPtr doc, xmlNode *a_node) {
437    char *prop;    char *prop;
438    member_t *member = g_new0(member_t, 1);    member_t *member = g_new0(member_t, 1);
439    member->type = ILLEGAL;    member->object.type = ILLEGAL;
440    
441    if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"type"))) {    if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"type"))) {
442      if(strcasecmp(prop, "way") == 0)           member->type = WAY;      if(strcasecmp(prop, "way") == 0)           member->object.type = WAY;
443      else if(strcasecmp(prop, "node") == 0)     member->type = NODE;      else if(strcasecmp(prop, "node") == 0)     member->object.type = NODE;
444      else if(strcasecmp(prop, "relation") == 0) member->type = RELATION;      else if(strcasecmp(prop, "relation") == 0) member->object.type = RELATION;
445      xmlFree(prop);      xmlFree(prop);
446    }    }
447    
448    if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"ref"))) {    if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"ref"))) {
449      item_id_t id = strtoul(prop, NULL, 10);      item_id_t id = strtoul(prop, NULL, 10);
450    
451      switch(member->type) {      switch(member->object.type) {
452      case ILLEGAL:      case ILLEGAL:
453        printf("Unable to store illegal type\n");        printf("Unable to store illegal type\n");
454        break;        break;
455    
456      case WAY:      case WAY:
457        /* search matching way */        /* search matching way */
458        member->way = osm_get_way_by_id(osm, id);        member->object.way = osm_get_way_by_id(osm, id);
459        if(!member->way) {        if(!member->object.way) {
460          member->type = WAY_ID;          member->object.type = WAY_ID;
461          member->id = id;          member->object.id = id;
462        }        }
463        break;        break;
464    
465      case NODE:      case NODE:
466        /* search matching node */        /* search matching node */
467        member->node = osm_get_node_by_id(osm, id);        member->object.node = osm_get_node_by_id(osm, id);
468        if(!member->node) {        if(!member->object.node) {
469          member->type = NODE_ID;          member->object.type = NODE_ID;
470          member->id = id;          member->object.id = id;
471        }        }
472        break;        break;
473    
474      case RELATION:      case RELATION:
475        /* search matching relation */        /* search matching relation */
476        member->relation = osm_get_relation_by_id(osm, id);        member->object.relation = osm_get_relation_by_id(osm, id);
477        if(!member->relation) {        if(!member->object.relation) {
478          member->type = NODE_ID;          member->object.type = NODE_ID;
479          member->id = id;          member->object.id = id;
480        }        }
481        break;        break;
482    
# Line 685  static node_t *process_node(xmlTextReade Line 679  static node_t *process_node(xmlTextReade
679      xmlFree(prop);      xmlFree(prop);
680    }    }
681    
682      /* new in api 0.6: */
683      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version"))) {
684        node->version = strtoul(prop, NULL, 10);
685        xmlFree(prop);
686      }
687    
688    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "lat"))) {    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "lat"))) {
689      node->pos.lat = g_ascii_strtod(prop, NULL);      node->pos.lat = g_ascii_strtod(prop, NULL);
690      xmlFree(prop);      xmlFree(prop);
# Line 759  static node_chain_t *process_nd(xmlTextR Line 759  static node_chain_t *process_nd(xmlTextR
759    
760      /* search matching node */      /* search matching node */
761      node_chain->node = osm_get_node_by_id(osm, id);      node_chain->node = osm_get_node_by_id(osm, id);
762      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id " ITEM_ID_FORMAT " not found\n", id);
763      else                  node_chain->node->ways++;      else                  node_chain->node->ways++;
764    
765      xmlFree(prop);      xmlFree(prop);
# Line 782  static way_t *process_way(xmlTextReaderP Line 782  static way_t *process_way(xmlTextReaderP
782      xmlFree(prop);      xmlFree(prop);
783    }    }
784    
785      /* new in api 0.6: */
786      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version"))) {
787        way->version = strtoul(prop, NULL, 10);
788        xmlFree(prop);
789      }
790    
791    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {
792      way->user = osm_user(osm, prop);      way->user = osm_user(osm, prop);
793      xmlFree(prop);      xmlFree(prop);
# Line 842  static way_t *process_way(xmlTextReaderP Line 848  static way_t *process_way(xmlTextReaderP
848  static member_t *process_member(xmlTextReaderPtr reader, osm_t *osm) {  static member_t *process_member(xmlTextReaderPtr reader, osm_t *osm) {
849    char *prop;    char *prop;
850    member_t *member = g_new0(member_t, 1);    member_t *member = g_new0(member_t, 1);
851    member->type = ILLEGAL;    member->object.type = ILLEGAL;
852    
853    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "type"))) {    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "type"))) {
854      if(strcasecmp(prop, "way") == 0)           member->type = WAY;      if(strcasecmp(prop, "way") == 0)           member->object.type = WAY;
855      else if(strcasecmp(prop, "node") == 0)     member->type = NODE;      else if(strcasecmp(prop, "node") == 0)     member->object.type = NODE;
856      else if(strcasecmp(prop, "relation") == 0) member->type = RELATION;      else if(strcasecmp(prop, "relation") == 0) member->object.type = RELATION;
857      xmlFree(prop);      xmlFree(prop);
858    }    }
859    
860    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "ref"))) {    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "ref"))) {
861      item_id_t id = strtoul(prop, NULL, 10);      item_id_t id = strtoul(prop, NULL, 10);
862    
863      switch(member->type) {      switch(member->object.type) {
864      case ILLEGAL:      case ILLEGAL:
865        printf("Unable to store illegal type\n");        printf("Unable to store illegal type\n");
866        break;        break;
867    
868      case WAY:      case WAY:
869        /* search matching way */        /* search matching way */
870        member->way = osm_get_way_by_id(osm, id);        member->object.way = osm_get_way_by_id(osm, id);
871        if(!member->way) {        if(!member->object.way) {
872          member->type = WAY_ID;          member->object.type = WAY_ID;
873          member->id = id;          member->object.id = id;
874        }        }
875        break;        break;
876    
877      case NODE:      case NODE:
878        /* search matching node */        /* search matching node */
879        member->node = osm_get_node_by_id(osm, id);        member->object.node = osm_get_node_by_id(osm, id);
880        if(!member->node) {        if(!member->object.node) {
881          member->type = NODE_ID;          member->object.type = NODE_ID;
882          member->id = id;          member->object.id = id;
883        }        }
884        break;        break;
885    
886      case RELATION:      case RELATION:
887        /* search matching relation */        /* search matching relation */
888        member->relation = osm_get_relation_by_id(osm, id);        member->object.relation = osm_get_relation_by_id(osm, id);
889        if(!member->relation) {        if(!member->object.relation) {
890          member->type = NODE_ID;          member->object.type = NODE_ID;
891          member->id = id;          member->object.id = id;
892        }        }
893        break;        break;
894    
# Line 913  static relation_t *process_relation(xmlT Line 919  static relation_t *process_relation(xmlT
919      xmlFree(prop);      xmlFree(prop);
920    }    }
921    
922      /* new in api 0.6: */
923      if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version"))) {
924        relation->version = strtoul(prop, NULL, 10);
925        xmlFree(prop);
926      }
927    
928    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {    if((prop = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "user"))) {
929      relation->user = osm_user(osm, prop);      relation->user = osm_user(osm, prop);
930      xmlFree(prop);      xmlFree(prop);
# Line 1156  gboolean osm_node_has_value(node_t *node Line 1168  gboolean osm_node_has_value(node_t *node
1168  gboolean osm_node_has_tag(node_t *node) {  gboolean osm_node_has_tag(node_t *node) {
1169    tag_t *tag = node->tag;    tag_t *tag = node->tag;
1170    
1171      /* created_by tags don't count as real tags */
1172    if(tag && strcasecmp(tag->key, "created_by") == 0)    if(tag && strcasecmp(tag->key, "created_by") == 0)
1173      tag = tag->next;      tag = tag->next;
1174    
# Line 1178  static void osm_generate_tags(tag_t *tag Line 1191  static void osm_generate_tags(tag_t *tag
1191    while(tag) {    while(tag) {
1192      /* make sure "created_by" tag contains our id */      /* make sure "created_by" tag contains our id */
1193      if(strcasecmp(tag->key, "created_by") == 0) {      if(strcasecmp(tag->key, "created_by") == 0) {
1194        g_free(tag->value);        if(strcasecmp(tag->value, PACKAGE " v" VERSION) != 0) {
1195        tag->value = g_strdup(PACKAGE " v" VERSION);          g_free(tag->value);
1196            tag->value = g_strdup(PACKAGE " v" VERSION);
1197          }
1198      }      }
1199    
1200      xmlNodePtr tag_node = xmlNewChild(node, NULL, BAD_CAST "tag", NULL);      xmlNodePtr tag_node = xmlNewChild(node, NULL, BAD_CAST "tag", NULL);
# Line 1190  static void osm_generate_tags(tag_t *tag Line 1205  static void osm_generate_tags(tag_t *tag
1205  }  }
1206    
1207  /* build xml representation for a way */  /* build xml representation for a way */
1208  char *osm_generate_xml(osm_t *osm, type_t type, void *item) {  static char *osm_generate_xml(osm_t *osm, item_id_t changeset,
1209                           type_t type, void *item) {
1210    char str[32];    char str[32];
1211    xmlChar *result = NULL;    xmlChar *result = NULL;
1212    int len = 0;    int len = 0;
# Line 1199  char *osm_generate_xml(osm_t *osm, type_ Line 1215  char *osm_generate_xml(osm_t *osm, type_
1215    
1216    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
1217    xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "osm");    xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "osm");
1218    #ifndef API06
1219    xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0.5");    xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0.5");
1220    xmlNewProp(root_node, BAD_CAST "generator", BAD_CAST PACKAGE " V" VERSION);    xmlNewProp(root_node, BAD_CAST "generator", BAD_CAST PACKAGE " v" VERSION);
1221    #endif
1222    xmlDocSetRootElement(doc, root_node);    xmlDocSetRootElement(doc, root_node);
1223    
1224    switch(type) {    switch(type) {
# Line 1214  char *osm_generate_xml(osm_t *osm, type_ Line 1232  char *osm_generate_xml(osm_t *osm, type_
1232          snprintf(str, sizeof(str), "%u", (unsigned)node->id);          snprintf(str, sizeof(str), "%u", (unsigned)node->id);
1233          xmlNewProp(node_node, BAD_CAST "id", BAD_CAST str);          xmlNewProp(node_node, BAD_CAST "id", BAD_CAST str);
1234        }        }
1235        g_ascii_dtostr(str, sizeof(str), node->pos.lat);  #ifdef API06
1236          snprintf(str, sizeof(str), "%u", (unsigned)node->version);
1237          xmlNewProp(node_node, BAD_CAST "version", BAD_CAST str);
1238          snprintf(str, sizeof(str), "%u", (unsigned)changeset);
1239          xmlNewProp(node_node, BAD_CAST "changeset", BAD_CAST str);
1240    #endif
1241          g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lat);
1242        xmlNewProp(node_node, BAD_CAST "lat", BAD_CAST str);        xmlNewProp(node_node, BAD_CAST "lat", BAD_CAST str);
1243        g_ascii_dtostr(str, sizeof(str), node->pos.lon);        g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lon);
1244        xmlNewProp(node_node, BAD_CAST "lon", BAD_CAST str);        xmlNewProp(node_node, BAD_CAST "lon", BAD_CAST str);
1245        osm_generate_tags(node->tag, node_node);        osm_generate_tags(node->tag, node_node);
1246      }      }
# Line 1228  char *osm_generate_xml(osm_t *osm, type_ Line 1252  char *osm_generate_xml(osm_t *osm, type_
1252        xmlNodePtr way_node = xmlNewChild(root_node, NULL, BAD_CAST "way", NULL);        xmlNodePtr way_node = xmlNewChild(root_node, NULL, BAD_CAST "way", NULL);
1253        snprintf(str, sizeof(str), "%u", (unsigned)way->id);        snprintf(str, sizeof(str), "%u", (unsigned)way->id);
1254        xmlNewProp(way_node, BAD_CAST "id", BAD_CAST str);        xmlNewProp(way_node, BAD_CAST "id", BAD_CAST str);
1255    #ifdef API06
1256          snprintf(str, sizeof(str), "%u", (unsigned)way->version);
1257          xmlNewProp(way_node, BAD_CAST "version", BAD_CAST str);
1258          snprintf(str, sizeof(str), "%u", (unsigned)changeset);
1259          xmlNewProp(way_node, BAD_CAST "changeset", BAD_CAST str);
1260    #endif
1261    
1262        node_chain_t *node_chain = way->node_chain;        node_chain_t *node_chain = way->node_chain;
1263        while(node_chain) {        while(node_chain) {
1264          xmlNodePtr nd_node = xmlNewChild(way_node, NULL, BAD_CAST "nd", NULL);          xmlNodePtr nd_node = xmlNewChild(way_node, NULL, BAD_CAST "nd", NULL);
1265          char *str = g_strdup_printf("%ld", node_chain->node->id);          char *str = g_strdup_printf(ITEM_ID_FORMAT, node_chain->node->id);
1266          xmlNewProp(nd_node, BAD_CAST "ref", BAD_CAST str);          xmlNewProp(nd_node, BAD_CAST "ref", BAD_CAST str);
1267          g_free(str);          g_free(str);
1268          node_chain = node_chain->next;          node_chain = node_chain->next;
# Line 1249  char *osm_generate_xml(osm_t *osm, type_ Line 1279  char *osm_generate_xml(osm_t *osm, type_
1279                                          BAD_CAST "relation", NULL);                                          BAD_CAST "relation", NULL);
1280        snprintf(str, sizeof(str), "%u", (unsigned)relation->id);        snprintf(str, sizeof(str), "%u", (unsigned)relation->id);
1281        xmlNewProp(rel_node, BAD_CAST "id", BAD_CAST str);        xmlNewProp(rel_node, BAD_CAST "id", BAD_CAST str);
1282    #ifdef API06
1283          snprintf(str, sizeof(str), "%u", (unsigned)relation->version);
1284          xmlNewProp(rel_node, BAD_CAST "version", BAD_CAST str);
1285          snprintf(str, sizeof(str), "%u", (unsigned)changeset);
1286          xmlNewProp(rel_node, BAD_CAST "changeset", BAD_CAST str);
1287    #endif
1288    
1289        member_t *member = relation->member;        member_t *member = relation->member;
1290        while(member) {        while(member) {
1291          xmlNodePtr m_node = xmlNewChild(rel_node,NULL,BAD_CAST "member", NULL);          xmlNodePtr m_node = xmlNewChild(rel_node,NULL,BAD_CAST "member", NULL);
1292          char *str = NULL;          char *str = NULL;
1293    
1294          switch(member->type) {          switch(member->object.type) {
1295          case NODE:          case NODE:
1296            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "node");            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "node");
1297            str = g_strdup_printf("%ld", member->node->id);            str = g_strdup_printf(ITEM_ID_FORMAT, member->object.node->id);
1298            break;            break;
1299    
1300          case WAY:          case WAY:
1301            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "way");            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "way");
1302            str = g_strdup_printf("%ld", member->way->id);            str = g_strdup_printf(ITEM_ID_FORMAT, member->object.way->id);
1303            break;            break;
1304    
1305          case RELATION:          case RELATION:
1306            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "relation");            xmlNewProp(m_node, BAD_CAST "type", BAD_CAST "relation");
1307            str = g_strdup_printf("%ld", member->relation->id);            str = g_strdup_printf(ITEM_ID_FORMAT, member->object.relation->id);
1308            break;            break;
1309    
1310          default:          default:
# Line 1308  char *osm_generate_xml(osm_t *osm, type_ Line 1344  char *osm_generate_xml(osm_t *osm, type_
1344  }  }
1345    
1346  /* build xml representation for a node */  /* build xml representation for a node */
1347  char *osm_generate_xml_node(osm_t *osm, node_t *node) {  char *osm_generate_xml_node(osm_t *osm, item_id_t changeset, node_t *node) {
1348    return osm_generate_xml(osm, NODE, node);    return osm_generate_xml(osm, changeset, NODE, node);
1349  }  }
1350    
1351  /* build xml representation for a way */  /* build xml representation for a way */
1352  char *osm_generate_xml_way(osm_t *osm, way_t *way) {  char *osm_generate_xml_way(osm_t *osm, item_id_t changeset, way_t *way) {
1353    return osm_generate_xml(osm, WAY, way);    return osm_generate_xml(osm, changeset, WAY, way);
1354  }  }
1355    
1356  /* build xml representation for a relation */  /* build xml representation for a relation */
1357  char *osm_generate_xml_relation(osm_t *osm, relation_t *relation) {  char *osm_generate_xml_relation(osm_t *osm, item_id_t changeset,
1358    return osm_generate_xml(osm, RELATION, relation);                                  relation_t *relation) {
1359      return osm_generate_xml(osm, changeset, RELATION, relation);
1360    }
1361    
1362    /* build xml representation for a changeset */
1363    char *osm_generate_xml_changeset(osm_t *osm, char *comment) {
1364      xmlChar *result = NULL;
1365      int len = 0;
1366    
1367      /* tags for this changeset */
1368      tag_t tag_comment = {
1369        .key = "comment", .value = comment, .next = NULL };
1370      tag_t tag_creator = {
1371        .key = "created_by", .value = PACKAGE " v" VERSION, .next = &tag_comment };
1372    
1373      LIBXML_TEST_VERSION;
1374    
1375      xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
1376      xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "osm");
1377      xmlDocSetRootElement(doc, root_node);
1378    
1379      xmlNodePtr cs_node = xmlNewChild(root_node, NULL, BAD_CAST "changeset", NULL);
1380      osm_generate_tags(&tag_creator, cs_node);
1381    
1382      xmlDocDumpFormatMemoryEnc(doc, &result, &len, "UTF-8", 1);
1383      xmlFreeDoc(doc);
1384      xmlCleanupParser();
1385    
1386      //  puts("xml encoding result:");
1387      //  puts((char*)result);
1388    
1389      return (char*)result;
1390  }  }
1391    
1392    
1393  /* the following three functions are eating much CPU power */  /* the following three functions are eating much CPU power */
1394  /* as they search the objects lists. Hashing is supposed to help */  /* as they search the objects lists. Hashing is supposed to help */
1395  node_t *osm_get_node_by_id(osm_t *osm, item_id_t id) {  node_t *osm_get_node_by_id(osm_t *osm, item_id_t id) {
# Line 1457  node_t *osm_node_new(osm_t *osm, gint x, Line 1525  node_t *osm_node_new(osm_t *osm, gint x,
1525    printf("Creating new node\n");    printf("Creating new node\n");
1526    
1527    node_t *node = g_new0(node_t, 1);    node_t *node = g_new0(node_t, 1);
1528      node->version = 1;
1529    node->lpos.x = x;    node->lpos.x = x;
1530    node->lpos.y = y;    node->lpos.y = y;
1531    node->visible = TRUE;    node->visible = TRUE;
1532    node->time = time(NULL);    node->time = time(NULL);
1533    
1534    #ifndef API06
1535    /* add created_by tag */    /* add created_by tag */
1536    node->tag = g_new0(tag_t, 1);    node->tag = g_new0(tag_t, 1);
1537    node->tag->key = g_strdup("created_by");    node->tag->key = g_strdup("created_by");
1538    node->tag->value = g_strdup(PACKAGE " v" VERSION);    node->tag->value = g_strdup(PACKAGE " v" VERSION);
1539    #endif
1540    
1541    /* convert screen position back to ll */    /* convert screen position back to ll */
1542    lpos2pos(osm->bounds, &node->lpos, &node->pos);    lpos2pos(osm->bounds, &node->lpos, &node->pos);
# Line 1502  way_t *osm_way_new(void) { Line 1573  way_t *osm_way_new(void) {
1573    printf("Creating new way\n");    printf("Creating new way\n");
1574    
1575    way_t *way = g_new0(way_t, 1);    way_t *way = g_new0(way_t, 1);
1576      way->version = 1;
1577    way->visible = TRUE;    way->visible = TRUE;
1578    way->flags = OSM_FLAG_NEW;    way->flags = OSM_FLAG_NEW;
1579    way->time = time(NULL);    way->time = time(NULL);
1580    
1581    #ifndef API06
1582    /* add created_by tag */    /* add created_by tag */
1583    way->tag = g_new0(tag_t, 1);    way->tag = g_new0(tag_t, 1);
1584    way->tag->key = g_strdup("created_by");    way->tag->key = g_strdup("created_by");
1585    way->tag->value = g_strdup(PACKAGE " v" VERSION);    way->tag->value = g_strdup(PACKAGE " v" VERSION);
1586    #endif
1587    
1588    return way;    return way;
1589  }  }
# Line 1534  way_chain_t *osm_node_delete(osm_t *osm, Line 1608  way_chain_t *osm_node_delete(osm_t *osm,
1608    
1609    /* new nodes aren't stored on the server and are just deleted permanently */    /* new nodes aren't stored on the server and are just deleted permanently */
1610    if(node->flags & OSM_FLAG_NEW) {    if(node->flags & OSM_FLAG_NEW) {
1611      printf("About to delete NEW node #%ld -> force permanent delete\n",      printf("About to delete NEW node #" ITEM_ID_FORMAT
1612             node->id);             " -> force permanent delete\n", node->id);
1613      permanently = TRUE;      permanently = TRUE;
1614    }    }
1615    
# Line 1571  way_chain_t *osm_node_delete(osm_t *osm, Line 1645  way_chain_t *osm_node_delete(osm_t *osm,
1645    }    }
1646    
1647    if(!permanently) {    if(!permanently) {
1648      printf("mark node #%ld as deleted\n", node->id);      printf("mark node #" ITEM_ID_FORMAT " as deleted\n", node->id);
1649      node->flags |= OSM_FLAG_DELETED;      node->flags |= OSM_FLAG_DELETED;
1650    } else {    } else {
1651      printf("permanently delete node #%ld\n", node->id);      printf("permanently delete node #" ITEM_ID_FORMAT "\n", node->id);
1652    
1653      /* remove it from the chain */      /* remove it from the chain */
1654      node_t **cnode = &osm->node;      node_t **cnode = &osm->node;
# Line 1615  relation_chain_t *osm_node_to_relation(o Line 1689  relation_chain_t *osm_node_to_relation(o
1689    
1690      member_t *member = relation->member;      member_t *member = relation->member;
1691      while(member) {      while(member) {
1692        switch(member->type) {        switch(member->object.type) {
1693        case NODE:        case NODE:
1694          /* nodes are checked directly */          /* nodes are checked directly */
1695          if(member->node == node)          if(member->object.node == node)
1696            is_member = TRUE;            is_member = TRUE;
1697          break;          break;
1698    
1699        case WAY: {        case WAY: {
1700          /* ways have to be checked for the nodes they consist of */          /* ways have to be checked for the nodes they consist of */
1701          node_chain_t *chain = member->way->node_chain;          node_chain_t *chain = member->object.way->node_chain;
1702          while(chain && !is_member) {          while(chain && !is_member) {
1703            if(chain->node == node)            if(chain->node == node)
1704              is_member = TRUE;              is_member = TRUE;
# Line 1662  relation_chain_t *osm_way_to_relation(os Line 1736  relation_chain_t *osm_way_to_relation(os
1736    
1737      member_t *member = relation->member;      member_t *member = relation->member;
1738      while(member) {      while(member) {
1739        switch(member->type) {        switch(member->object.type) {
1740        case WAY: {        case WAY: {
1741          /* ways can be check directly */          /* ways can be check directly */
1742          if(member->way == way)          if(member->object.way == way)
1743            is_member = TRUE;            is_member = TRUE;
1744        } break;        } break;
1745    
# Line 1727  gboolean osm_position_within_bounds(osm_ Line 1801  gboolean osm_position_within_bounds(osm_
1801  /* be deleted */  /* be deleted */
1802  void osm_node_remove_from_relation(osm_t *osm, node_t *node) {  void osm_node_remove_from_relation(osm_t *osm, node_t *node) {
1803    relation_t *relation = osm->relation;    relation_t *relation = osm->relation;
1804    printf("removing node #%ld from all relations:\n", node->id);    printf("removing node #" ITEM_ID_FORMAT " from all relations:\n", node->id);
1805    
1806    while(relation) {    while(relation) {
1807      member_t **member = &relation->member;      member_t **member = &relation->member;
1808      while(*member) {      while(*member) {
1809        if(((*member)->type == NODE) &&        if(((*member)->object.type == NODE) &&
1810           ((*member)->node == node)) {           ((*member)->object.node == node)) {
1811    
1812          printf("  from relation #%ld\n", relation->id);          printf("  from relation #" ITEM_ID_FORMAT "\n", relation->id);
1813    
1814          member_t *cur = *member;          member_t *cur = *member;
1815          *member = (*member)->next;          *member = (*member)->next;
# Line 1752  void osm_node_remove_from_relation(osm_t Line 1826  void osm_node_remove_from_relation(osm_t
1826  /* remove the given way from all relations */  /* remove the given way from all relations */
1827  void osm_way_remove_from_relation(osm_t *osm, way_t *way) {  void osm_way_remove_from_relation(osm_t *osm, way_t *way) {
1828    relation_t *relation = osm->relation;    relation_t *relation = osm->relation;
1829    printf("removing way #%ld from all relations:\n", way->id);    printf("removing way #" ITEM_ID_FORMAT " from all relations:\n", way->id);
1830    
1831    while(relation) {    while(relation) {
1832      member_t **member = &relation->member;      member_t **member = &relation->member;
1833      while(*member) {      while(*member) {
1834        if(((*member)->type == WAY) &&        if(((*member)->object.type == WAY) &&
1835           ((*member)->way == way)) {           ((*member)->object.way == way)) {
1836    
1837          printf("  from relation #%ld\n", relation->id);          printf("  from relation #" ITEM_ID_FORMAT "\n", relation->id);
1838    
1839          member_t *cur = *member;          member_t *cur = *member;
1840          *member = (*member)->next;          *member = (*member)->next;
# Line 1778  relation_t *osm_relation_new(void) { Line 1852  relation_t *osm_relation_new(void) {
1852    printf("Creating new relation\n");    printf("Creating new relation\n");
1853    
1854    relation_t *relation = g_new0(relation_t, 1);    relation_t *relation = g_new0(relation_t, 1);
1855      relation->version = 1;
1856    relation->visible = TRUE;    relation->visible = TRUE;
1857    relation->flags = OSM_FLAG_NEW;    relation->flags = OSM_FLAG_NEW;
1858    relation->time = time(NULL);    relation->time = time(NULL);
1859    
1860    #ifndef API06
1861    /* add created_by tag */    /* add created_by tag */
1862    relation->tag = g_new0(tag_t, 1);    relation->tag = g_new0(tag_t, 1);
1863    relation->tag->key = g_strdup("created_by");    relation->tag->key = g_strdup("created_by");
1864    relation->tag->value = g_strdup(PACKAGE " v" VERSION);    relation->tag->value = g_strdup(PACKAGE " v" VERSION);
1865    #endif
1866    
1867    return relation;    return relation;
1868  }  }
# Line 1808  void osm_way_delete(osm_t *osm, icon_t * Line 1885  void osm_way_delete(osm_t *osm, icon_t *
1885    
1886    /* new ways aren't stored on the server and are just deleted permanently */    /* new ways aren't stored on the server and are just deleted permanently */
1887    if(way->flags & OSM_FLAG_NEW) {    if(way->flags & OSM_FLAG_NEW) {
1888      printf("About to delete NEW way #%ld -> force permanent delete\n",      printf("About to delete NEW way #" ITEM_ID_FORMAT
1889             way->id);             " -> force permanent delete\n", way->id);
1890      permanently = TRUE;      permanently = TRUE;
1891    }    }
1892    
# Line 1818  void osm_way_delete(osm_t *osm, icon_t * Line 1895  void osm_way_delete(osm_t *osm, icon_t *
1895    while(*chain) {    while(*chain) {
1896    
1897      (*chain)->node->ways--;      (*chain)->node->ways--;
1898      printf("checking node #%ld (still used by %d)\n",      printf("checking node #" ITEM_ID_FORMAT " (still used by %d)\n",
1899             (*chain)->node->id, (*chain)->node->ways);             (*chain)->node->id, (*chain)->node->ways);
1900    
1901      /* this node must only be part of this way */      /* this node must only be part of this way */
# Line 1844  void osm_way_delete(osm_t *osm, icon_t * Line 1921  void osm_way_delete(osm_t *osm, icon_t *
1921    way->node_chain = NULL;    way->node_chain = NULL;
1922    
1923    if(!permanently) {    if(!permanently) {
1924      printf("mark way #%ld as deleted\n", way->id);      printf("mark way #" ITEM_ID_FORMAT " as deleted\n", way->id);
1925      way->flags |= OSM_FLAG_DELETED;      way->flags |= OSM_FLAG_DELETED;
1926    } else {    } else {
1927      printf("permanently delete way #%ld\n", way->id);      printf("permanently delete way #" ITEM_ID_FORMAT "\n", way->id);
1928    
1929      /* remove it from the chain */      /* remove it from the chain */
1930      way_t **cway = &osm->way;      way_t **cway = &osm->way;
# Line 1872  void osm_relation_delete(osm_t *osm, rel Line 1949  void osm_relation_delete(osm_t *osm, rel
1949    /* new relations aren't stored on the server and are just */    /* new relations aren't stored on the server and are just */
1950    /* deleted permanently */    /* deleted permanently */
1951    if(relation->flags & OSM_FLAG_NEW) {    if(relation->flags & OSM_FLAG_NEW) {
1952      printf("About to delete NEW relation #%ld -> force permanent delete\n",      printf("About to delete NEW relation #" ITEM_ID_FORMAT
1953             relation->id);             " -> force permanent delete\n", relation->id);
1954      permanently = TRUE;      permanently = TRUE;
1955    }    }
1956    
# Line 1881  void osm_relation_delete(osm_t *osm, rel Line 1958  void osm_relation_delete(osm_t *osm, rel
1958    /* don't have any reference to the relation they are part of */    /* don't have any reference to the relation they are part of */
1959    
1960    if(!permanently) {    if(!permanently) {
1961      printf("mark relation #%ld as deleted\n", relation->id);      printf("mark relation #" ITEM_ID_FORMAT " as deleted\n", relation->id);
1962      relation->flags |= OSM_FLAG_DELETED;      relation->flags |= OSM_FLAG_DELETED;
1963    } else {    } else {
1964      printf("permanently delete relation #%ld\n", relation->id);      printf("permanently delete relation #" ITEM_ID_FORMAT "\n", relation->id);
1965    
1966      /* remove it from the chain */      /* remove it from the chain */
1967      relation_t **crelation = &osm->relation;      relation_t **crelation = &osm->relation;
# Line 2011  osm_way_reverse_direction_sensitive_role Line 2088  osm_way_reverse_direction_sensitive_role
2088        // First find the member corresponding to our way:        // First find the member corresponding to our way:
2089        member_t *member = rel_chain->relation->member;        member_t *member = rel_chain->relation->member;
2090        for (; member != NULL; member = member->next) {        for (; member != NULL; member = member->next) {
2091          if (member->type == WAY) {          if (member->object.type == WAY) {
2092            if (member->way == way)            if (member->object.way == way)
2093              break;              break;
2094          }          }
2095          if (member->type == WAY_ID) {          if (member->object.type == WAY_ID) {
2096            if (member->id == way->id)            if (member->object.id == way->id)
2097              break;              break;
2098          }          }
2099        }        }
2100        g_assert(member);  // osm_way_to_relation() broken?        g_assert(member);  // osm_way_to_relation() broken?
2101    
2102        // Then flip its role if it's one of the direction-sensitive ones        // Then flip its role if it's one of the direction-sensitive ones
2103        if (strcasecmp(member->role, DS_ROUTE_FORWARD) == 0) {        if (member->role == NULL) {
2104            printf("null role in route relation -> ignore\n");
2105          }
2106          else if (strcasecmp(member->role, DS_ROUTE_FORWARD) == 0) {
2107          g_free(member->role);          g_free(member->role);
2108          member->role = g_strdup(DS_ROUTE_REVERSE);          member->role = g_strdup(DS_ROUTE_REVERSE);
2109          rel_chain->relation->flags |= OSM_FLAG_DIRTY;          rel_chain->relation->flags |= OSM_FLAG_DIRTY;
# Line 2109  tag_t *osm_tags_copy(tag_t *src_tag, gbo Line 2189  tag_t *osm_tags_copy(tag_t *src_tag, gbo
2189  }  }
2190    
2191  /* return plain text of type */  /* return plain text of type */
2192  char *osm_type_string(type_t type) {  char *osm_object_type_string(object_t *object) {
2193    const struct { type_t type; char *name; } types[] = {    const struct { type_t type; char *name; } types[] = {
2194      { ILLEGAL,     "illegal" },      { ILLEGAL,     "illegal" },
2195      { NODE,        "node" },      { NODE,        "node" },
# Line 2123  char *osm_type_string(type_t type) { Line 2203  char *osm_type_string(type_t type) {
2203    
2204    int i;    int i;
2205    for(i=0;types[i].name;i++)    for(i=0;types[i].name;i++)
2206      if(type == types[i].type)      if(object->type == types[i].type)
2207        return types[i].name;        return types[i].name;
2208    
2209    return NULL;    return NULL;
2210  }  }
2211    
2212  char *osm_object_string(type_t type, void *object) {  char *osm_object_string(object_t *object) {
2213    char *type_str = osm_type_string(type);    char *type_str = osm_object_type_string(object);
2214    
2215    if(!object)    if(!object)
2216      return g_strdup_printf("%s #<invalid>", type_str);      return g_strdup_printf("%s #<invalid>", type_str);
2217    
2218    switch(type) {    switch(object->type) {
2219    case ILLEGAL:    case ILLEGAL:
2220      return g_strdup_printf("%s #<unspec>", type_str);      return g_strdup_printf("%s #<unspec>", type_str);
2221      break;      break;
2222    case NODE:    case NODE:
2223      return g_strdup_printf("%s #%ld", type_str, ((node_t*)object)->id);      return g_strdup_printf("%s #" ITEM_ID_FORMAT, type_str, object->node->id);
2224      break;      break;
2225    case WAY:    case WAY:
2226      return g_strdup_printf("%s #%ld", type_str, ((way_t*)object)->id);      return g_strdup_printf("%s #" ITEM_ID_FORMAT, type_str, object->way->id);
2227      break;      break;
2228    case RELATION:    case RELATION:
2229      return g_strdup_printf("%s #%ld", type_str, ((relation_t*)object)->id);      return g_strdup_printf("%s #" ITEM_ID_FORMAT, type_str,
2230                               object->relation->id);
2231      break;      break;
2232    case NODE_ID:    case NODE_ID:
2233    case WAY_ID:    case WAY_ID:
2234    case RELATION_ID:    case RELATION_ID:
2235      return g_strdup_printf("%s #%ld", type_str, ((item_id_t)object));      return g_strdup_printf("%s #" ITEM_ID_FORMAT, type_str, object->id);
2236      break;      break;
2237    }    }
2238    return NULL;    return NULL;
2239  }  }
2240    
2241  char *osm_id_string(type_t type, void *object) {  char *osm_object_id_string(object_t *object) {
2242    if(!object) return NULL;    if(!object) return NULL;
2243    
2244    switch(type) {    switch(object->type) {
2245    case ILLEGAL:    case ILLEGAL:
2246      return NULL;      return NULL;
2247      break;      break;
2248    case NODE:    case NODE:
2249      return g_strdup_printf("#%ld", ((node_t*)object)->id);      return g_strdup_printf("#"ITEM_ID_FORMAT, object->node->id);
2250      break;      break;
2251    case WAY:    case WAY:
2252      return g_strdup_printf("#%ld", ((way_t*)object)->id);      return g_strdup_printf("#"ITEM_ID_FORMAT, object->way->id);
2253      break;      break;
2254    case RELATION:    case RELATION:
2255      return g_strdup_printf("#%ld", ((relation_t*)object)->id);      return g_strdup_printf("#"ITEM_ID_FORMAT, object->relation->id);
2256      break;      break;
2257    case NODE_ID:    case NODE_ID:
2258    case WAY_ID:    case WAY_ID:
2259    case RELATION_ID:    case RELATION_ID:
2260      return g_strdup_printf("#%ld", ((item_id_t)object));      return g_strdup_printf("#"ITEM_ID_FORMAT, object->id);
2261      break;      break;
2262    }    }
2263    return NULL;    return NULL;
2264  }  }
2265    
2266  tag_t *osm_object_get_tags(type_t type, void *object) {  tag_t *osm_object_get_tags(object_t *object) {
2267    if(!object) return NULL;    if(!object) return NULL;
2268    
2269    switch(type) {    switch(object->type) {
2270    case ILLEGAL:    case ILLEGAL:
2271      return NULL;      return NULL;
2272      break;      break;
2273    case NODE:    case NODE:
2274      return ((node_t*)object)->tag;      return object->node->tag;
2275      break;      break;
2276    case WAY:    case WAY:
2277      return ((way_t*)object)->tag;      return object->way->tag;
2278      break;      break;
2279    case RELATION:    case RELATION:
2280      return ((relation_t*)object)->tag;      return object->relation->tag;
2281      break;      break;
2282    case NODE_ID:    case NODE_ID:
2283    case WAY_ID:    case WAY_ID:
# Line 2218  gint osm_relation_members_num(relation_t Line 2299  gint osm_relation_members_num(relation_t
2299    return num;    return num;
2300  }  }
2301    
2302    void osm_object_set_flags(object_t *object, int set, int clr) {
2303    
2304      switch(object->type) {
2305      case NODE:
2306        object->node->flags |=  set;
2307        object->node->flags &= ~clr;
2308        break;
2309    
2310      case WAY:
2311        object->way->flags |=  set;
2312        object->way->flags &= ~clr;
2313        break;
2314    
2315      case RELATION:
2316        object->relation->flags |=  set;
2317        object->relation->flags &= ~clr;
2318        break;
2319    
2320      default:
2321        g_assert(0);
2322        break;
2323      }
2324    }
2325    
2326  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.98  
changed lines
  Added in v.161