Diff of /trunk/src/osm.c

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

revision 40 by harbaum, Sun Jan 18 19:43:20 2009 UTC revision 73 by harbaum, Thu Feb 12 14:27:52 2009 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  /* xml parsing has a performance issue */  /* these defines select one of three possible xml parsers */
21    /* this is in fact selected depending on the plattform in the Makefile */
22  // #define OSM_DOM_PARSER  // #define OSM_DOM_PARSER
23  // #define OSM_STREAM_PARSER  // #define OSM_STREAM_PARSER
 #define OSM_QND_XML_PARSER  
24    
25  #include <stdio.h>  #include <stdio.h>
26  #include <stdlib.h>  #include <stdlib.h>
# Line 370  static node_t *osm_parse_osm_node(osm_t Line 370  static node_t *osm_parse_osm_node(osm_t
370      xmlFree(prop);      xmlFree(prop);
371    }    }
372    
373      /* append node to end of hash table if present */
374      if(osm->node_hash) {
375        hash_item_t **item = &osm->node_hash->hash[ID2HASH(node->id)];
376        while(*item) item = &(*item)->next;
377    
378        *item = g_new0(hash_item_t, 1);
379        (*item)->data.node = node;
380      }
381    
382    /* scan for tags and attach a list of tags */    /* scan for tags and attach a list of tags */
383    tag_t **tag = &node->tag;    tag_t **tag = &node->tag;
384    for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {    for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {
# Line 481  node_chain_t *osm_parse_osm_way_nd(osm_t Line 490  node_chain_t *osm_parse_osm_way_nd(osm_t
490      node_chain_t *node_chain = g_new0(node_chain_t, 1);      node_chain_t *node_chain = g_new0(node_chain_t, 1);
491    
492      /* search matching node */      /* search matching node */
493      node_chain->node = osm->node;      node_chain->node = osm_get_node_by_id(osm, id);
     while(node_chain->node && node_chain->node->id != id)  
       node_chain->node = node_chain->node->next;  
   
494      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id %lu not found\n", id);
495        else                  node_chain->node->ways++;
     if(node_chain->node)  
       node_chain->node->ways++;  
496    
497      xmlFree(prop);      xmlFree(prop);
498    
# Line 527  static way_t *osm_parse_osm_way(osm_t *o Line 531  static way_t *osm_parse_osm_way(osm_t *o
531      xmlFree(prop);      xmlFree(prop);
532    }    }
533    
534      /* append way to end of hash table if present */
535      if(osm->way_hash) {
536        hash_item_t **item = &osm->way_hash->hash[ID2HASH(way->id)];
537        while(*item) item = &(*item)->next;
538    
539        *item = g_new0(hash_item_t, 1);
540        (*item)->data.way = way;
541      }
542    
543    /* scan for tags/nodes and attach their lists */    /* scan for tags/nodes and attach their lists */
544    tag_t **tag = &way->tag;    tag_t **tag = &way->tag;
545    node_chain_t **node_chain = &way->node_chain;    node_chain_t **node_chain = &way->node_chain;
# Line 565  void osm_members_free(member_t *member) Line 578  void osm_members_free(member_t *member)
578    }    }
579  }  }
580    
581    void osm_relation_free(relation_t *relation) {
582      osm_tags_free(relation->tag);
583      osm_members_free(relation->member);
584    
585      g_free(relation);
586    }
587    
588  static void osm_relations_free(relation_t *relation) {  static void osm_relations_free(relation_t *relation) {
589    while(relation) {    while(relation) {
590      relation_t *next = relation->next;      relation_t *next = relation->next;
591        osm_relation_free(relation);
     osm_tags_free(relation->tag);  
     osm_members_free(relation->member);  
   
     g_free(relation);  
592      relation = next;      relation = next;
593    }    }
594  }  }
# Line 652  member_t *osm_parse_osm_relation_member( Line 668  member_t *osm_parse_osm_relation_member(
668    
669      case WAY:      case WAY:
670        /* search matching way */        /* search matching way */
671        member->way = osm->way;        member->way = osm_get_way_by_id(osm, id);
       while(member->way && member->way->id != id)  
         member->way = member->way->next;  
   
672        if(!member->way) {        if(!member->way) {
673          member->type = WAY_ID;          member->type = WAY_ID;
674          member->id = id;          member->id = id;
# Line 664  member_t *osm_parse_osm_relation_member( Line 677  member_t *osm_parse_osm_relation_member(
677    
678      case NODE:      case NODE:
679        /* search matching node */        /* search matching node */
680        member->node = osm->node;        member->node = osm_get_node_by_id(osm, id);
       while(member->node && member->node->id != id)  
         member->node = member->node->next;  
   
681        if(!member->node) {        if(!member->node) {
682          member->type = NODE_ID;          member->type = NODE_ID;
683          member->id = id;          member->id = id;
# Line 676  member_t *osm_parse_osm_relation_member( Line 686  member_t *osm_parse_osm_relation_member(
686    
687      case RELATION:      case RELATION:
688        /* search matching relation */        /* search matching relation */
689        member->relation = osm->relation;        member->relation = osm_get_relation_by_id(osm, id);
       while(member->relation && member->relation->id != id)  
         member->relation = member->relation->next;  
   
690        if(!member->relation) {        if(!member->relation) {
691          member->type = NODE_ID;          member->type = NODE_ID;
692          member->id = id;          member->id = id;
# Line 755  static relation_t *osm_parse_osm_relatio Line 762  static relation_t *osm_parse_osm_relatio
762    
763  /* ----------------------- generic xml handling -------------------------- */  /* ----------------------- generic xml handling -------------------------- */
764    
765  /* parse loc entry */  /* parse osm entry */
766  static void osm_parse_osm(osm_t *osm, xmlDocPtr doc, xmlNode * a_node) {  static void osm_parse_osm(osm_t *osm, xmlDocPtr doc, xmlNode * a_node) {
767    xmlNode *cur_node = NULL;    xmlNode *cur_node = NULL;
768    
# Line 837  static osm_t *osm_parse_root(xmlDocPtr d Line 844  static osm_t *osm_parse_root(xmlDocPtr d
844    
845    /* allocate memory to hold osm file description */    /* allocate memory to hold osm file description */
846    osm = g_new0(osm_t, 1);    osm = g_new0(osm_t, 1);
847      osm->node_hash = g_new0(hash_table_t, 1);
848      osm->way_hash = g_new0(hash_table_t, 1);
849    
850    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
851      if (cur_node->type == XML_ELEMENT_NODE) {      if (cur_node->type == XML_ELEMENT_NODE) {
# Line 874  static osm_t *osm_parse_doc(xmlDocPtr do Line 883  static osm_t *osm_parse_doc(xmlDocPtr do
883    
884  /* ------------------ osm handling ----------------- */  /* ------------------ osm handling ----------------- */
885    
886    /* the two hash tables eat over 512kBytes memory and may thus be */
887    /* freed at any time. osm2go can work without them (albeit slower) */
888    static void hash_table_free(hash_table_t *table) {
889      if(!table) return;
890    
891      int i;
892      for(i=0;i<65536;i++) {
893        hash_item_t *item = table->hash[i];
894        while(item) {
895          hash_item_t *next = item->next;
896          g_free(item);
897          item = next;
898        }
899      }
900    }
901    
902    void osm_hash_tables_free(osm_t *osm) {
903      hash_table_free(osm->node_hash);
904      osm->node_hash = NULL;
905      hash_table_free(osm->way_hash);
906      osm->way_hash = NULL;
907    }
908    
909  void osm_free(icon_t **icon, osm_t *osm) {  void osm_free(icon_t **icon, osm_t *osm) {
910    if(!osm) return;    if(!osm) return;
911    
912      osm_hash_tables_free(osm);
913    
914    if(osm->bounds)   osm_bounds_free(osm->bounds);    if(osm->bounds)   osm_bounds_free(osm->bounds);
915    if(osm->user)     osm_users_free(osm->user);    if(osm->user)     osm_users_free(osm->user);
916    if(osm->way)      osm_ways_free(osm->way);    if(osm->way)      osm_ways_free(osm->way);
# Line 1057  static node_t *process_node(xmlTextReade Line 1091  static node_t *process_node(xmlTextReade
1091    
1092    pos2lpos(osm->bounds, &node->pos, &node->lpos);    pos2lpos(osm->bounds, &node->pos, &node->lpos);
1093    
1094      /* append node to end of hash table if present */
1095      if(osm->node_hash) {
1096        hash_item_t **item = &osm->node_hash->hash[ID2HASH(node->id)];
1097        while(*item) item = &(*item)->next;
1098    
1099        *item = g_new0(hash_item_t, 1);
1100        (*item)->data.node = node;
1101      }
1102    
1103    /* just an empty element? then return the node as it is */    /* just an empty element? then return the node as it is */
1104    if(xmlTextReaderIsEmptyElement(reader))    if(xmlTextReaderIsEmptyElement(reader))
1105      return node;      return node;
# Line 1094  static node_chain_t *process_nd(xmlTextR Line 1137  static node_chain_t *process_nd(xmlTextR
1137      node_chain_t *node_chain = g_new0(node_chain_t, 1);      node_chain_t *node_chain = g_new0(node_chain_t, 1);
1138    
1139      /* search matching node */      /* search matching node */
1140      node_chain->node = osm->node;      node_chain->node = osm_get_node_by_id(osm, id);
     while(node_chain->node && node_chain->node->id != id)  
       node_chain->node = node_chain->node->next;  
   
1141      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id %lu not found\n", id);
1142        else                  node_chain->node->ways++;
     if(node_chain->node)  
       node_chain->node->ways++;  
1143    
1144      xmlFree(prop);      xmlFree(prop);
1145    
# Line 1138  static way_t *process_way(xmlTextReaderP Line 1176  static way_t *process_way(xmlTextReaderP
1176      xmlFree(prop);      xmlFree(prop);
1177    }    }
1178    
1179      /* append way to end of hash table if present */
1180      if(osm->way_hash) {
1181        hash_item_t **item = &osm->way_hash->hash[ID2HASH(way->id)];
1182        while(*item) item = &(*item)->next;
1183    
1184        *item = g_new0(hash_item_t, 1);
1185        (*item)->data.way = way;
1186      }
1187    
1188    /* just an empty element? then return the way as it is */    /* just an empty element? then return the way as it is */
1189    /* (this should in fact never happen as this would be a way without nodes) */    /* (this should in fact never happen as this would be a way without nodes) */
1190    if(xmlTextReaderIsEmptyElement(reader))    if(xmlTextReaderIsEmptyElement(reader))
# Line 1193  static member_t *process_member(xmlTextR Line 1240  static member_t *process_member(xmlTextR
1240    
1241      case WAY:      case WAY:
1242        /* search matching way */        /* search matching way */
1243        member->way = osm->way;        member->way = osm_get_way_by_id(osm, id);
       while(member->way && member->way->id != id)  
         member->way = member->way->next;  
   
1244        if(!member->way) {        if(!member->way) {
1245          member->type = WAY_ID;          member->type = WAY_ID;
1246          member->id = id;          member->id = id;
# Line 1205  static member_t *process_member(xmlTextR Line 1249  static member_t *process_member(xmlTextR
1249    
1250      case NODE:      case NODE:
1251        /* search matching node */        /* search matching node */
1252        member->node = osm->node;        member->node = osm_get_node_by_id(osm, id);
       while(member->node && member->node->id != id)  
         member->node = member->node->next;  
   
1253        if(!member->node) {        if(!member->node) {
1254          member->type = NODE_ID;          member->type = NODE_ID;
1255          member->id = id;          member->id = id;
# Line 1217  static member_t *process_member(xmlTextR Line 1258  static member_t *process_member(xmlTextR
1258    
1259      case RELATION:      case RELATION:
1260        /* search matching relation */        /* search matching relation */
1261        member->relation = osm->relation;        member->relation = osm_get_relation_by_id(osm, id);
       while(member->relation && member->relation->id != id)  
         member->relation = member->relation->next;  
   
1262        if(!member->relation) {        if(!member->relation) {
1263          member->type = NODE_ID;          member->type = NODE_ID;
1264          member->id = id;          member->id = id;
# Line 1306  static relation_t *process_relation(xmlT Line 1344  static relation_t *process_relation(xmlT
1344  static osm_t *process_osm(xmlTextReaderPtr reader) {  static osm_t *process_osm(xmlTextReaderPtr reader) {
1345    /* alloc osm structure */    /* alloc osm structure */
1346    osm_t *osm = g_new0(osm_t, 1);    osm_t *osm = g_new0(osm_t, 1);
1347      osm->node_hash = g_new0(hash_table_t, 1);
1348      osm->way_hash = g_new0(hash_table_t, 1);
1349    
1350    node_t **node = &osm->node;    node_t **node = &osm->node;
1351    way_t **way = &osm->way;    way_t **way = &osm->way;
# Line 1500  static gboolean osm_node_cb(qnd_xml_stac Line 1540  static gboolean osm_node_cb(qnd_xml_stac
1540    /* store current tag pointer in userdata for fast access to current tag */    /* store current tag pointer in userdata for fast access to current tag */
1541    stack->userdata[1] = &node->tag;    stack->userdata[1] = &node->tag;
1542    
1543      /* append node to end of hash table if present */
1544      if(osm->node_hash) {
1545        hash_item_t **item = &osm->node_hash->hash[ID2HASH(node->id)];
1546        while(*item) item = &(*item)->next;
1547    
1548        *item = g_new0(hash_item_t, 1);
1549        (*item)->data.node = node;
1550      }
1551    
1552    return TRUE;    return TRUE;
1553  }  }
1554    
# Line 1515  static gboolean osm_way_nd_cb(qnd_xml_st Line 1564  static gboolean osm_way_nd_cb(qnd_xml_st
1564        g_new0(node_chain_t, 1);        g_new0(node_chain_t, 1);
1565    
1566      /* search matching node */      /* search matching node */
1567      node_chain->node = osm->node;      node_chain->node = osm_get_node_by_id(osm, id);
     while(node_chain->node && node_chain->node->id != id)  
       node_chain->node = node_chain->node->next;  
   
1568      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id %lu not found\n", id);
1569        else                  node_chain->node->ways++;
     if(node_chain->node)  
       node_chain->node->ways++;  
1570    
1571      stack->prev->userdata[2] = &node_chain->next;      stack->prev->userdata[2] = &node_chain->next;
1572    }    }
# Line 1551  gboolean osm_way_cb(qnd_xml_stack_t *sta Line 1595  gboolean osm_way_cb(qnd_xml_stack_t *sta
1595    stack->userdata[1] = &way->tag;    stack->userdata[1] = &way->tag;
1596    stack->userdata[2] = &way->node_chain;    stack->userdata[2] = &way->node_chain;
1597    
1598      /* append way to end of hash table if present */
1599      if(osm->way_hash) {
1600        hash_item_t **item = &osm->way_hash->hash[ID2HASH(way->id)];
1601        while(*item) item = &(*item)->next;
1602    
1603        *item = g_new0(hash_item_t, 1);
1604        (*item)->data.way = way;
1605      }
1606    
1607    return TRUE;    return TRUE;
1608  }  }
1609    
# Line 1580  static gboolean osm_rel_member_cb(qnd_xm Line 1633  static gboolean osm_rel_member_cb(qnd_xm
1633    
1634      case WAY:      case WAY:
1635        /* search matching way */        /* search matching way */
1636        member->way = osm->way;        member->way = osm_get_way_by_id(osm, id);
       while(member->way && member->way->id != id)  
         member->way = member->way->next;  
   
1637        if(!member->way) {        if(!member->way) {
1638          member->type = WAY_ID;          member->type = WAY_ID;
1639          member->id = id;          member->id = id;
# Line 1592  static gboolean osm_rel_member_cb(qnd_xm Line 1642  static gboolean osm_rel_member_cb(qnd_xm
1642    
1643      case NODE:      case NODE:
1644        /* search matching node */        /* search matching node */
1645        member->node = osm->node;        member->node = osm_get_node_by_id(osm, id);
       while(member->node && member->node->id != id)  
         member->node = member->node->next;  
   
1646        if(!member->node) {        if(!member->node) {
1647          member->type = NODE_ID;          member->type = NODE_ID;
1648          member->id = id;          member->id = id;
# Line 1604  static gboolean osm_rel_member_cb(qnd_xm Line 1651  static gboolean osm_rel_member_cb(qnd_xm
1651    
1652      case RELATION:      case RELATION:
1653        /* search matching relation */        /* search matching relation */
1654        member->relation = osm->relation;        member->relation = osm_get_relation_by_id(osm, id);
       while(member->relation && member->relation->id != id)  
         member->relation = member->relation->next;  
   
1655        if(!member->relation) {        if(!member->relation) {
1656          member->type = NODE_ID;          member->type = NODE_ID;
1657          member->id = id;          member->id = id;
# Line 1657  gboolean osm_cb(qnd_xml_stack_t *stack, Line 1701  gboolean osm_cb(qnd_xml_stack_t *stack,
1701    osm_t *osm = stack->prev->userdata[0] =    osm_t *osm = stack->prev->userdata[0] =
1702      stack->userdata[0] = g_new0(osm_t, 1);      stack->userdata[0] = g_new0(osm_t, 1);
1703    
1704      osm->node_hash = g_new0(hash_table_t, 1);
1705      osm->way_hash = g_new0(hash_table_t, 1);
1706    
1707    /* store direct pointers for faster list access */    /* store direct pointers for faster list access */
1708    /* (otherwise we'd have to search the end of the lists for every item */    /* (otherwise we'd have to search the end of the lists for every item */
1709    /* to be attached) */    /* to be attached) */
# Line 1712  osm_t *osm_parse(char *filename) { Line 1759  osm_t *osm_parse(char *filename) {
1759    struct timeval start;    struct timeval start;
1760    gettimeofday(&start, NULL);    gettimeofday(&start, NULL);
1761    
   
1762  #ifdef OSM_STREAM_PARSER  #ifdef OSM_STREAM_PARSER
1763    LIBXML_TEST_VERSION;    LIBXML_TEST_VERSION;
1764    
# Line 2002  char *osm_generate_xml_relation(osm_t *o Line 2048  char *osm_generate_xml_relation(osm_t *o
2048    return osm_generate_xml(osm, RELATION, relation);    return osm_generate_xml(osm, RELATION, relation);
2049  }  }
2050    
2051    /* the following three functions are eating much CPU power */
2052    /* as they search the objects lists. Hashing is supposed to help */
2053  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) {
2054      if(id > 0 && osm->node_hash) {
2055        // use hash table if present
2056        hash_item_t *item = osm->node_hash->hash[ID2HASH(id)];
2057        while(item) {
2058          if(item->data.node->id == id)
2059            return item->data.node;
2060    
2061          item = item->next;
2062        }
2063      }
2064    
2065      /* use linear search if no hash tables are present or search in hash table failed */
2066    node_t *node = osm->node;    node_t *node = osm->node;
2067    while(node) {    while(node) {
2068      if(node->id == id)      if(node->id == id)
2069        return node;        return node;
2070    
2071      node = node->next;      node = node->next;
2072    }    }
2073    
2074    return NULL;    return NULL;
2075  }  }
2076    
2077  way_t *osm_get_way_by_id(osm_t *osm, item_id_t id) {  way_t *osm_get_way_by_id(osm_t *osm, item_id_t id) {
2078      if(id > 0 && osm->way_hash) {
2079        // use hash table if present
2080        hash_item_t *item = osm->way_hash->hash[ID2HASH(id)];
2081        while(item) {
2082          if(item->data.way->id == id)
2083            return item->data.way;
2084    
2085          item = item->next;
2086        }
2087      }
2088    
2089      /* use linear search if no hash tables are present or search on hash table failed */
2090    way_t *way = osm->way;    way_t *way = osm->way;
2091    while(way) {    while(way) {
2092      if(way->id == id)      if(way->id == id)
2093        return way;        return way;
2094    
2095      way = way->next;      way = way->next;
2096    }    }
2097    
2098    return NULL;    return NULL;
2099  }  }
2100    
2101  relation_t *osm_get_relation_by_id(osm_t *osm, item_id_t id) {  relation_t *osm_get_relation_by_id(osm_t *osm, item_id_t id) {
2102      // use linear search
2103    relation_t *relation = osm->relation;    relation_t *relation = osm->relation;
2104    while(relation) {    while(relation) {
2105      if(relation->id == id)      if(relation->id == id)
# Line 2082  item_id_t osm_new_node_id(osm_t *osm) { Line 2157  item_id_t osm_new_node_id(osm_t *osm) {
2157    return 0;    return 0;
2158  }  }
2159    
2160    item_id_t osm_new_relation_id(osm_t *osm) {
2161      item_id_t id = -1;
2162    
2163      while(TRUE) {
2164        gboolean found = FALSE;
2165        relation_t *relation = osm->relation;
2166        while(relation) {
2167          if(relation->id == id)
2168            found = TRUE;
2169    
2170          relation = relation->next;
2171        }
2172    
2173        /* no such id so far -> use it */
2174        if(!found) return id;
2175    
2176        id--;
2177      }
2178      g_assert(0);
2179      return 0;
2180    }
2181    
2182  node_t *osm_node_new(osm_t *osm, gint x, gint y) {  node_t *osm_node_new(osm_t *osm, gint x, gint y) {
2183    printf("Creating new node\n");    printf("Creating new node\n");
2184    
# Line 2118  void osm_node_attach(osm_t *osm, node_t Line 2215  void osm_node_attach(osm_t *osm, node_t
2215    *lnode = node;    *lnode = node;
2216  }  }
2217    
2218    void osm_node_restore(osm_t *osm, node_t *node) {
2219      printf("Restoring node\n");
2220    
2221      /* attach to end of node list */
2222      node_t **lnode = &osm->node;
2223      while(*lnode) lnode = &(*lnode)->next;
2224      *lnode = node;
2225    }
2226    
2227  way_t *osm_way_new(void) {  way_t *osm_way_new(void) {
2228    printf("Creating new way\n");    printf("Creating new way\n");
2229    
# Line 2394  void osm_way_remove_from_relation(osm_t Line 2500  void osm_way_remove_from_relation(osm_t
2500    }    }
2501  }  }
2502    
2503    relation_t *osm_relation_new(void) {
2504      printf("Creating new relation\n");
2505    
2506      relation_t *relation = g_new0(relation_t, 1);
2507      relation->visible = TRUE;
2508      relation->flags = OSM_FLAG_NEW;
2509      relation->time = time(NULL);
2510    
2511      /* add created_by tag */
2512      relation->tag = g_new0(tag_t, 1);
2513      relation->tag->key = g_strdup("created_by");
2514      relation->tag->value = g_strdup(PACKAGE " v" VERSION);
2515    
2516      return relation;
2517    }
2518    
2519    void osm_relation_attach(osm_t *osm, relation_t *relation) {
2520      printf("Attaching relation\n");
2521    
2522      relation->id = osm_new_relation_id(osm);
2523      relation->flags = OSM_FLAG_NEW;
2524    
2525      /* attach to end of relation list */
2526      relation_t **lrelation = &osm->relation;
2527      while(*lrelation) lrelation = &(*lrelation)->next;
2528      *lrelation = relation;
2529    }
2530    
2531    
2532  void osm_way_delete(osm_t *osm, icon_t **icon,  void osm_way_delete(osm_t *osm, icon_t **icon,
2533                      way_t *way, gboolean permanently) {                      way_t *way, gboolean permanently) {
2534    
# Line 2532  tag_t *osm_tags_copy(tag_t *src_tag, gbo Line 2667  tag_t *osm_tags_copy(tag_t *src_tag, gbo
2667    
2668    return new_tags;    return new_tags;
2669  }  }
2670    
2671    /* return plain text of type */
2672    char *osm_type_string(type_t type) {
2673      const struct { type_t type; char *name; } types[] = {
2674        { ILLEGAL,     "illegal" },
2675        { NODE,        "node" },
2676        { WAY,         "way" },
2677        { RELATION,    "relation" },
2678        { NODE_ID,     "node id" },
2679        { WAY_ID,      "way id" },
2680        { RELATION_ID, "relation id" },
2681        { 0, NULL }
2682      };
2683    
2684      int i;
2685      for(i=0;types[i].name;i++)
2686        if(type == types[i].type)
2687          return types[i].name;
2688    
2689      return NULL;
2690    }
2691    
2692    char *osm_object_string(type_t type, void *object) {
2693      char *type_str = osm_type_string(type);
2694    
2695      if(!object)
2696        return g_strdup_printf("%s #<invalid>", type_str);
2697    
2698      switch(type) {
2699      case ILLEGAL:
2700        return g_strdup_printf("%s #<unspec>", type_str);
2701        break;
2702      case NODE:
2703        return g_strdup_printf("%s #%ld", type_str, ((node_t*)object)->id);
2704        break;
2705      case WAY:
2706        return g_strdup_printf("%s #%ld", type_str, ((way_t*)object)->id);
2707        break;
2708      case RELATION:
2709        return g_strdup_printf("%s #%ld", type_str, ((relation_t*)object)->id);
2710        break;
2711      case NODE_ID:
2712      case WAY_ID:
2713      case RELATION_ID:
2714        return g_strdup_printf("%s #%ld", type_str, *((item_id_t*)object));
2715        break;
2716      }
2717      return NULL;
2718    }
2719    
2720  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.40  
changed lines
  Added in v.73