Diff of /trunk/src/osm.c

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

revision 28 by achadwick, Wed Dec 24 14:17:20 2008 UTC revision 78 by harbaum, Sun Feb 15 12:07:04 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    
 #define OSM_STREAM_PARSER  
   
20  #include <stdio.h>  #include <stdio.h>
21  #include <stdlib.h>  #include <stdlib.h>
22  #include <string.h>  #include <string.h>
# Line 55  static void osm_bounds_dump(bounds_t *bo Line 53  static void osm_bounds_dump(bounds_t *bo
53           bounds->ll_min.lon, bounds->ll_max.lon);           bounds->ll_min.lon, bounds->ll_max.lon);
54  }  }
55    
 #ifndef OSM_STREAM_PARSER  
 static bounds_t *osm_parse_osm_bounds(osm_t *osm,  
                      xmlDocPtr doc, xmlNode *a_node) {  
   char *prop;  
   
   if(osm->bounds) {  
     errorf(NULL, "Doubly defined bounds");  
     return NULL;  
   }  
   
   bounds_t *bounds = g_new0(bounds_t, 1);  
   
   bounds->ll_min.lat = bounds->ll_min.lon = NAN;  
   bounds->ll_max.lat = bounds->ll_max.lon = NAN;  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"minlat"))) {  
     bounds->ll_min.lat = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"maxlat"))) {  
     bounds->ll_max.lat = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"minlon"))) {  
     bounds->ll_min.lon = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"maxlon"))) {  
     bounds->ll_max.lon = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if(isnan(bounds->ll_min.lat) || isnan(bounds->ll_min.lon) ||  
      isnan(bounds->ll_max.lat) || isnan(bounds->ll_max.lon)) {  
     errorf(NULL, "Invalid coordinate in bounds (%f/%f/%f/%f)",  
            bounds->ll_min.lat, bounds->ll_min.lon,  
            bounds->ll_max.lat, bounds->ll_max.lon);  
   
     osm_bounds_free(bounds);  
     return NULL;  
   }  
   
   
   /* calculate map zone which will be used as a reference for all */  
   /* drawing/projection later on */  
   pos_t center = { (bounds->ll_max.lat + bounds->ll_min.lat)/2,  
                    (bounds->ll_max.lon + bounds->ll_min.lon)/2 };  
   
   pos2lpos_center(&center, &bounds->center);  
   
   /* the scale is needed to accomodate for "streching" */  
   /* by the mercartor projection */  
   bounds->scale = cos(DEG2RAD(center.lat));  
   
   pos2lpos_center(&bounds->ll_min, &bounds->min);  
   bounds->min.x -= bounds->center.x;  
   bounds->min.y -= bounds->center.y;  
   bounds->min.x *= bounds->scale;  
   bounds->min.y *= bounds->scale;  
   
   pos2lpos_center(&bounds->ll_max, &bounds->max);  
   bounds->max.x -= bounds->center.x;  
   bounds->max.y -= bounds->center.y;  
   bounds->max.x *= bounds->scale;  
   bounds->max.y *= bounds->scale;  
   
   return bounds;  
 }  
 #endif  
   
56  /* ------------------------- user handling --------------------- */  /* ------------------------- user handling --------------------- */
57    
58  void osm_users_free(user_t *user) {  void osm_users_free(user_t *user) {
# Line 150  void osm_users_dump(user_t *user) { Line 75  void osm_users_dump(user_t *user) {
75  }  }
76    
77  static user_t *osm_user(osm_t *osm, char *name) {  static user_t *osm_user(osm_t *osm, char *name) {
78      if(!name) return NULL;
79    
80    /* search through user list */    /* search through user list */
81    user_t **user = &osm->user;    user_t **user = &osm->user;
# Line 171  static user_t *osm_user(osm_t *osm, char Line 97  static user_t *osm_user(osm_t *osm, char
97    
98  static  static
99  time_t convert_iso8601(const char *str) {  time_t convert_iso8601(const char *str) {
100      if(!str) return 0;
101    
102    tzset();    tzset();
103    
104    struct tm ctime;    struct tm ctime;
# Line 324  void osm_nodes_dump(node_t *node) { Line 252  void osm_nodes_dump(node_t *node) {
252    }    }
253  }  }
254    
 #ifndef OSM_STREAM_PARSER  
 static node_t *osm_parse_osm_node(osm_t *osm,  
                           xmlDocPtr doc, xmlNode *a_node) {  
   xmlNode *cur_node = NULL;  
   
   /* allocate a new node structure */  
   node_t *node = g_new0(node_t, 1);  
   node->pos.lat = node->pos.lon = NAN;  
   
   char *prop;  
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"id"))) {  
     node->id = strtoul(prop, NULL, 10);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"lat"))) {  
     node->pos.lat = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"lon"))) {  
     node->pos.lon = g_ascii_strtod(prop, NULL);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"user"))) {  
     node->user = osm_user(osm, prop);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"visible"))) {  
     node->visible = (strcasecmp(prop, "true") == 0);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"timestamp"))) {  
     node->time = convert_iso8601(prop);  
     xmlFree(prop);  
   }  
   
   /* scan for tags and attach a list of tags */  
   tag_t **tag = &node->tag;  
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {  
     if (cur_node->type == XML_ELEMENT_NODE) {  
       if(strcasecmp((char*)cur_node->name, "tag") == 0) {  
         /* attach tag to node */  
         *tag = osm_parse_osm_tag(osm, doc, cur_node);  
         if(*tag) tag = &((*tag)->next);  
       } else  
         printf("found unhandled osm/node/%s\n", cur_node->name);  
     }  
   }  
   
   pos2lpos(osm->bounds, &node->pos, &node->lpos);  
   
   return node;  
 }  
 #endif  
   
255  /* ------------------- way handling ------------------- */  /* ------------------- way handling ------------------- */
256    
257  void osm_node_chain_free(node_chain_t *node_chain) {  void osm_node_chain_free(node_chain_t *node_chain) {
# Line 475  node_chain_t *osm_parse_osm_way_nd(osm_t Line 344  node_chain_t *osm_parse_osm_way_nd(osm_t
344      node_chain_t *node_chain = g_new0(node_chain_t, 1);      node_chain_t *node_chain = g_new0(node_chain_t, 1);
345    
346      /* search matching node */      /* search matching node */
347      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;  
   
348      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id %lu not found\n", id);
349        else                  node_chain->node->ways++;
     if(node_chain->node)  
       node_chain->node->ways++;  
350    
351      xmlFree(prop);      xmlFree(prop);
352    
# Line 492  node_chain_t *osm_parse_osm_way_nd(osm_t Line 356  node_chain_t *osm_parse_osm_way_nd(osm_t
356    return NULL;    return NULL;
357  }  }
358    
 #ifndef OSM_STREAM_PARSER  
 static way_t *osm_parse_osm_way(osm_t *osm,  
                           xmlDocPtr doc, xmlNode *a_node) {  
   xmlNode *cur_node = NULL;  
   
   /* allocate a new way structure */  
   way_t *way = g_new0(way_t, 1);  
   
   char *prop;  
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"id"))) {  
     way->id = strtoul(prop, NULL, 10);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"user"))) {  
     way->user = osm_user(osm, prop);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"visible"))) {  
     way->visible = (strcasecmp(prop, "true") == 0);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"timestamp"))) {  
     way->time = convert_iso8601(prop);  
     xmlFree(prop);  
   }  
   
   /* scan for tags/nodes and attach their lists */  
   tag_t **tag = &way->tag;  
   node_chain_t **node_chain = &way->node_chain;  
   
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {  
     if (cur_node->type == XML_ELEMENT_NODE) {  
       if(strcasecmp((char*)cur_node->name, "tag") == 0) {  
         /* attach tag to node */  
         *tag = osm_parse_osm_tag(osm, doc, cur_node);  
         if(*tag) tag = &((*tag)->next);  
       } else if(strcasecmp((char*)cur_node->name, "nd") == 0) {  
         *node_chain = osm_parse_osm_way_nd(osm, doc, cur_node);  
         if(*node_chain)  
           node_chain = &((*node_chain)->next);  
       } else  
         printf("found unhandled osm/node/%s\n", cur_node->name);  
     }  
   }  
   
   return way;  
 }  
 #endif  
   
359  /* ------------------- relation handling ------------------- */  /* ------------------- relation handling ------------------- */
360    
361  void osm_member_free(member_t *member) {  void osm_member_free(member_t *member) {
# Line 559  void osm_members_free(member_t *member) Line 371  void osm_members_free(member_t *member)
371    }    }
372  }  }
373    
374    void osm_relation_free(relation_t *relation) {
375      osm_tags_free(relation->tag);
376      osm_members_free(relation->member);
377    
378      g_free(relation);
379    }
380    
381  static void osm_relations_free(relation_t *relation) {  static void osm_relations_free(relation_t *relation) {
382    while(relation) {    while(relation) {
383      relation_t *next = relation->next;      relation_t *next = relation->next;
384        osm_relation_free(relation);
     osm_tags_free(relation->tag);  
     osm_members_free(relation->member);  
   
     g_free(relation);  
385      relation = next;      relation = next;
386    }    }
387  }  }
# Line 646  member_t *osm_parse_osm_relation_member( Line 461  member_t *osm_parse_osm_relation_member(
461    
462      case WAY:      case WAY:
463        /* search matching way */        /* search matching way */
464        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;  
   
465        if(!member->way) {        if(!member->way) {
466          member->type = WAY_ID;          member->type = WAY_ID;
467          member->id = id;          member->id = id;
# Line 658  member_t *osm_parse_osm_relation_member( Line 470  member_t *osm_parse_osm_relation_member(
470    
471      case NODE:      case NODE:
472        /* search matching node */        /* search matching node */
473        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;  
   
474        if(!member->node) {        if(!member->node) {
475          member->type = NODE_ID;          member->type = NODE_ID;
476          member->id = id;          member->id = id;
# Line 670  member_t *osm_parse_osm_relation_member( Line 479  member_t *osm_parse_osm_relation_member(
479    
480      case RELATION:      case RELATION:
481        /* search matching relation */        /* search matching relation */
482        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;  
   
483        if(!member->relation) {        if(!member->relation) {
484          member->type = NODE_ID;          member->type = NODE_ID;
485          member->id = id;          member->id = id;
# Line 697  member_t *osm_parse_osm_relation_member( Line 503  member_t *osm_parse_osm_relation_member(
503    return member;    return member;
504  }  }
505    
506  #ifndef OSM_STREAM_PARSER  /* ------------------ osm handling ----------------- */
 static relation_t *osm_parse_osm_relation(osm_t *osm,  
                           xmlDocPtr doc, xmlNode *a_node) {  
   xmlNode *cur_node = NULL;  
   
   /* allocate a new relation structure */  
   relation_t *relation = g_new0(relation_t, 1);  
   
   char *prop;  
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"id"))) {  
     relation->id = strtoul(prop, NULL, 10);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"user"))) {  
     relation->user = osm_user(osm, prop);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"visible"))) {  
     relation->visible = (strcasecmp(prop, "true") == 0);  
     xmlFree(prop);  
   }  
   
   if((prop = (char*)xmlGetProp(a_node, (unsigned char*)"timestamp"))) {  
     relation->time = convert_iso8601(prop);  
     xmlFree(prop);  
   }  
   
   /* scan for tags and attach a list of tags */  
   tag_t **tag = &relation->tag;  
   member_t **member = &relation->member;  
   
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {  
     if (cur_node->type == XML_ELEMENT_NODE) {  
       if(strcasecmp((char*)cur_node->name, "tag") == 0) {  
         /* attach tag to node */  
         *tag = osm_parse_osm_tag(osm, doc, cur_node);  
         if(*tag) tag = &((*tag)->next);  
       } else if(strcasecmp((char*)cur_node->name, "member") == 0) {  
         *member = osm_parse_osm_relation_member(osm, doc, cur_node);  
         if(*member) member = &((*member)->next);  
       } else  
         printf("found unhandled osm/node/%s\n", cur_node->name);  
     }  
   }  
   
   return relation;  
 }  
   
 /* ----------------------- generic xml handling -------------------------- */  
   
 /* parse loc entry */  
 static void osm_parse_osm(osm_t *osm, xmlDocPtr doc, xmlNode * a_node) {  
   xmlNode *cur_node = NULL;  
   
   for (cur_node = a_node->children; cur_node; cur_node = cur_node->next) {  
     if (cur_node->type == XML_ELEMENT_NODE) {  
       if(strcasecmp((char*)cur_node->name, "bounds") == 0)  
         osm->bounds = osm_parse_osm_bounds(osm, doc, cur_node);  
       else if(strcasecmp((char*)cur_node->name, "node") == 0) {  
         /* parse node and attach it to chain */  
         node_t *new = osm_parse_osm_node(osm, doc, cur_node);  
         if(new) {  
           node_t **node = &osm->node;  
   
 #ifdef OSM_SORT_ID  
           /* search chain of nodes */  
           while(*node && ((*node)->id < new->id))  
             node = &(*node)->next;  
 #endif  
   
 #ifdef OSM_SORT_LAST  
           while(*node) node = &(*node)->next;  
 #endif  
   
           /* insert into chain */  
           new->next = *node;  
           *node = new;  
         }  
       } else if(strcasecmp((char*)cur_node->name, "way") == 0) {  
         /* parse way and attach it to chain */  
         way_t *new = osm_parse_osm_way(osm, doc, cur_node);  
         if(new) {  
           way_t **way = &osm->way;  
   
 #ifdef OSM_SORT_ID  
           /* insert into chain */  
           while(*way && ((*way)->id < new->id))  
             way = &(*way)->next;  
 #endif  
   
 #ifdef OSM_SORT_LAST  
           while(*way) way = &(*way)->next;  
 #endif  
   
           /* insert into chain */  
           new->next = *way;  
           *way = new;  
         }  
       } else if(strcasecmp((char*)cur_node->name, "relation") == 0) {  
         /* parse relation and attach it to chain */  
         relation_t *new = osm_parse_osm_relation(osm, doc, cur_node);  
         if(new) {  
           relation_t **relation = &osm->relation;  
   
 #ifdef OSM_SORT_ID  
           /* search chain of ways */  
           while(*relation && ((*relation)->id < new->id))  
             relation = &(*relation)->next;  
 #endif  
   
 #ifdef OSM_SORT_LAST  
           while(*relation) relation = &(*relation)->next;  
 #endif  
   
           /* insert into chain */  
           new->next = *relation;  
           *relation = new;  
         }  
       } else  
         printf("found unhandled osm/%s\n", cur_node->name);  
   
     }  
   }  
 }  
   
 /* parse root element and search for "osm" */  
 static osm_t *osm_parse_root(xmlDocPtr doc, xmlNode * a_node) {  
   osm_t *osm;  
   xmlNode *cur_node = NULL;  
   
   /* allocate memory to hold osm file description */  
   osm = g_new0(osm_t, 1);  
507    
508    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {  /* the two hash tables eat over 512kBytes memory and may thus be */
509      if (cur_node->type == XML_ELEMENT_NODE) {  /* freed at any time. osm2go can work without them (albeit slower) */
510        /* parse osm osm file ... */  static void hash_table_free(hash_table_t *table) {
511        if(strcasecmp((char*)cur_node->name, "osm") == 0)    if(!table) return;
512          osm_parse_osm(osm, doc, cur_node);  
513        else    int i;
514          printf("found unhandled %s\n", cur_node->name);    for(i=0;i<65536;i++) {
515        hash_item_t *item = table->hash[i];
516        while(item) {
517          hash_item_t *next = item->next;
518          g_free(item);
519          item = next;
520      }      }
521    }    }
   
   return osm;  
522  }  }
523    
524  static osm_t *osm_parse_doc(xmlDocPtr doc) {  void osm_hash_tables_free(osm_t *osm) {
525    osm_t *osm;    hash_table_free(osm->node_hash);
526      osm->node_hash = NULL;
527    /* Get the root element node */    hash_table_free(osm->way_hash);
528    xmlNode *root_element = xmlDocGetRootElement(doc);    osm->way_hash = NULL;
   
   osm = osm_parse_root(doc, root_element);  
   
   /*free the document */  
   xmlFreeDoc(doc);  
   
   /*  
    * Free the global variables that may  
    * have been allocated by the parser.  
    */  
   xmlCleanupParser();  
   
   return osm;  
529  }  }
 #endif  
   
 /* ------------------ osm handling ----------------- */  
530    
531  void osm_free(icon_t **icon, osm_t *osm) {  void osm_free(icon_t **icon, osm_t *osm) {
532    if(!osm) return;    if(!osm) return;
533    
534      osm_hash_tables_free(osm);
535    
536    if(osm->bounds)   osm_bounds_free(osm->bounds);    if(osm->bounds)   osm_bounds_free(osm->bounds);
537    if(osm->user)     osm_users_free(osm->user);    if(osm->user)     osm_users_free(osm->user);
538    if(osm->way)      osm_ways_free(osm->way);    if(osm->way)      osm_ways_free(osm->way);
# Line 887  void osm_dump(osm_t *osm) { Line 549  void osm_dump(osm_t *osm) {
549    osm_relations_dump(osm->relation);    osm_relations_dump(osm->relation);
550  }  }
551    
552  #ifdef OSM_STREAM_PARSER  /* -------------------------- stream parser ------------------- */
 /* -------------------------- stream parser tests ------------------- */  
553    
554  #include <libxml/xmlreader.h>  #include <libxml/xmlreader.h>
555    
# Line 1051  static node_t *process_node(xmlTextReade Line 712  static node_t *process_node(xmlTextReade
712    
713    pos2lpos(osm->bounds, &node->pos, &node->lpos);    pos2lpos(osm->bounds, &node->pos, &node->lpos);
714    
715      /* append node to end of hash table if present */
716      if(osm->node_hash) {
717        hash_item_t **item = &osm->node_hash->hash[ID2HASH(node->id)];
718        while(*item) item = &(*item)->next;
719    
720        *item = g_new0(hash_item_t, 1);
721        (*item)->data.node = node;
722      }
723    
724    /* just an empty element? then return the node as it is */    /* just an empty element? then return the node as it is */
725    if(xmlTextReaderIsEmptyElement(reader))    if(xmlTextReaderIsEmptyElement(reader))
726      return node;      return node;
# Line 1088  static node_chain_t *process_nd(xmlTextR Line 758  static node_chain_t *process_nd(xmlTextR
758      node_chain_t *node_chain = g_new0(node_chain_t, 1);      node_chain_t *node_chain = g_new0(node_chain_t, 1);
759    
760      /* search matching node */      /* search matching node */
761      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;  
   
762      if(!node_chain->node) printf("Node id %lu not found\n", id);      if(!node_chain->node) printf("Node id %lu not found\n", id);
763        else                  node_chain->node->ways++;
     if(node_chain->node)  
       node_chain->node->ways++;  
764    
765      xmlFree(prop);      xmlFree(prop);
766    
# Line 1132  static way_t *process_way(xmlTextReaderP Line 797  static way_t *process_way(xmlTextReaderP
797      xmlFree(prop);      xmlFree(prop);
798    }    }
799    
800      /* append way to end of hash table if present */
801      if(osm->way_hash) {
802        hash_item_t **item = &osm->way_hash->hash[ID2HASH(way->id)];
803        while(*item) item = &(*item)->next;
804    
805        *item = g_new0(hash_item_t, 1);
806        (*item)->data.way = way;
807      }
808    
809    /* just an empty element? then return the way as it is */    /* just an empty element? then return the way as it is */
810    /* (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) */
811    if(xmlTextReaderIsEmptyElement(reader))    if(xmlTextReaderIsEmptyElement(reader))
# Line 1187  static member_t *process_member(xmlTextR Line 861  static member_t *process_member(xmlTextR
861    
862      case WAY:      case WAY:
863        /* search matching way */        /* search matching way */
864        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;  
   
865        if(!member->way) {        if(!member->way) {
866          member->type = WAY_ID;          member->type = WAY_ID;
867          member->id = id;          member->id = id;
# Line 1199  static member_t *process_member(xmlTextR Line 870  static member_t *process_member(xmlTextR
870    
871      case NODE:      case NODE:
872        /* search matching node */        /* search matching node */
873        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;  
   
874        if(!member->node) {        if(!member->node) {
875          member->type = NODE_ID;          member->type = NODE_ID;
876          member->id = id;          member->id = id;
# Line 1211  static member_t *process_member(xmlTextR Line 879  static member_t *process_member(xmlTextR
879    
880      case RELATION:      case RELATION:
881        /* search matching relation */        /* search matching relation */
882        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;  
   
883        if(!member->relation) {        if(!member->relation) {
884          member->type = NODE_ID;          member->type = NODE_ID;
885          member->id = id;          member->id = id;
# Line 1282  static relation_t *process_relation(xmlT Line 947  static relation_t *process_relation(xmlT
947    
948      if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {      if(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
949        char *subname = (char*)xmlTextReaderConstName(reader);        char *subname = (char*)xmlTextReaderConstName(reader);
950        if(strcasecmp(subname, "nd") == 0) {        if(strcasecmp(subname, "member") == 0) {
951          *member = process_member(reader, osm);          *member = process_member(reader, osm);
952          if(*member) member = &(*member)->next;          if(*member) member = &(*member)->next;
953        } else if(strcasecmp(subname, "tag") == 0) {        } else if(strcasecmp(subname, "tag") == 0) {
# Line 1300  static relation_t *process_relation(xmlT Line 965  static relation_t *process_relation(xmlT
965  static osm_t *process_osm(xmlTextReaderPtr reader) {  static osm_t *process_osm(xmlTextReaderPtr reader) {
966    /* alloc osm structure */    /* alloc osm structure */
967    osm_t *osm = g_new0(osm_t, 1);    osm_t *osm = g_new0(osm_t, 1);
968      osm->node_hash = g_new0(hash_table_t, 1);
969      osm->way_hash = g_new0(hash_table_t, 1);
970    
971    node_t **node = &osm->node;    node_t **node = &osm->node;
972    way_t **way = &osm->way;    way_t **way = &osm->way;
# Line 1382  static osm_t *process_file(const char *f Line 1049  static osm_t *process_file(const char *f
1049    return osm;    return osm;
1050  }  }
1051    
1052  /* ----------------------- end of stream parser tests ------------------- */  /* ----------------------- end of stream parser ------------------- */
 #endif  
1053    
1054  #include <sys/time.h>  #include <sys/time.h>
1055    
# Line 1394  osm_t *osm_parse(char *filename) { Line 1060  osm_t *osm_parse(char *filename) {
1060    
1061    LIBXML_TEST_VERSION;    LIBXML_TEST_VERSION;
1062    
 #ifdef OSM_STREAM_PARSER  
1063    // use stream parser    // use stream parser
1064    osm_t *osm = process_file(filename);    osm_t *osm = process_file(filename);
1065    xmlCleanupParser();    xmlCleanupParser();
1066    
 #else  
   // parse into a tree  
   /* parse the file and get the DOM */  
   xmlDoc *doc = NULL;  
   if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {  
     xmlErrorPtr errP = xmlGetLastError();  
     errorf(NULL, "While parsing \"%s\":\n\n%s", filename, errP->message);  
     return NULL;  
   }  
   
   osm_t *osm = osm_parse_doc(doc);  
 #endif  
   
1067    struct timeval end;    struct timeval end;
1068    gettimeofday(&end, NULL);    gettimeofday(&end, NULL);
1069    
# Line 1670  char *osm_generate_xml_relation(osm_t *o Line 1322  char *osm_generate_xml_relation(osm_t *o
1322    return osm_generate_xml(osm, RELATION, relation);    return osm_generate_xml(osm, RELATION, relation);
1323  }  }
1324    
1325    /* the following three functions are eating much CPU power */
1326    /* as they search the objects lists. Hashing is supposed to help */
1327  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) {
1328      if(id > 0 && osm->node_hash) {
1329        // use hash table if present
1330        hash_item_t *item = osm->node_hash->hash[ID2HASH(id)];
1331        while(item) {
1332          if(item->data.node->id == id)
1333            return item->data.node;
1334    
1335          item = item->next;
1336        }
1337      }
1338    
1339      /* use linear search if no hash tables are present or search in hash table failed */
1340    node_t *node = osm->node;    node_t *node = osm->node;
1341    while(node) {    while(node) {
1342      if(node->id == id)      if(node->id == id)
1343        return node;        return node;
1344    
1345      node = node->next;      node = node->next;
1346    }    }
1347    
1348    return NULL;    return NULL;
1349  }  }
1350    
1351  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) {
1352      if(id > 0 && osm->way_hash) {
1353        // use hash table if present
1354        hash_item_t *item = osm->way_hash->hash[ID2HASH(id)];
1355        while(item) {
1356          if(item->data.way->id == id)
1357            return item->data.way;
1358    
1359          item = item->next;
1360        }
1361      }
1362    
1363      /* use linear search if no hash tables are present or search on hash table failed */
1364    way_t *way = osm->way;    way_t *way = osm->way;
1365    while(way) {    while(way) {
1366      if(way->id == id)      if(way->id == id)
1367        return way;        return way;
1368    
1369      way = way->next;      way = way->next;
1370    }    }
1371    
1372    return NULL;    return NULL;
1373  }  }
1374    
1375  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) {
1376      // use linear search
1377    relation_t *relation = osm->relation;    relation_t *relation = osm->relation;
1378    while(relation) {    while(relation) {
1379      if(relation->id == id)      if(relation->id == id)
# Line 1750  item_id_t osm_new_node_id(osm_t *osm) { Line 1431  item_id_t osm_new_node_id(osm_t *osm) {
1431    return 0;    return 0;
1432  }  }
1433    
1434    item_id_t osm_new_relation_id(osm_t *osm) {
1435      item_id_t id = -1;
1436    
1437      while(TRUE) {
1438        gboolean found = FALSE;
1439        relation_t *relation = osm->relation;
1440        while(relation) {
1441          if(relation->id == id)
1442            found = TRUE;
1443    
1444          relation = relation->next;
1445        }
1446    
1447        /* no such id so far -> use it */
1448        if(!found) return id;
1449    
1450        id--;
1451      }
1452      g_assert(0);
1453      return 0;
1454    }
1455    
1456  node_t *osm_node_new(osm_t *osm, gint x, gint y) {  node_t *osm_node_new(osm_t *osm, gint x, gint y) {
1457    printf("Creating new node\n");    printf("Creating new node\n");
1458    
# Line 1786  void osm_node_attach(osm_t *osm, node_t Line 1489  void osm_node_attach(osm_t *osm, node_t
1489    *lnode = node;    *lnode = node;
1490  }  }
1491    
1492    void osm_node_restore(osm_t *osm, node_t *node) {
1493      printf("Restoring node\n");
1494    
1495      /* attach to end of node list */
1496      node_t **lnode = &osm->node;
1497      while(*lnode) lnode = &(*lnode)->next;
1498      *lnode = node;
1499    }
1500    
1501  way_t *osm_way_new(void) {  way_t *osm_way_new(void) {
1502    printf("Creating new way\n");    printf("Creating new way\n");
1503    
# Line 2062  void osm_way_remove_from_relation(osm_t Line 1774  void osm_way_remove_from_relation(osm_t
1774    }    }
1775  }  }
1776    
1777    relation_t *osm_relation_new(void) {
1778      printf("Creating new relation\n");
1779    
1780      relation_t *relation = g_new0(relation_t, 1);
1781      relation->visible = TRUE;
1782      relation->flags = OSM_FLAG_NEW;
1783      relation->time = time(NULL);
1784    
1785      /* add created_by tag */
1786      relation->tag = g_new0(tag_t, 1);
1787      relation->tag->key = g_strdup("created_by");
1788      relation->tag->value = g_strdup(PACKAGE " v" VERSION);
1789    
1790      return relation;
1791    }
1792    
1793    void osm_relation_attach(osm_t *osm, relation_t *relation) {
1794      printf("Attaching relation\n");
1795    
1796      relation->id = osm_new_relation_id(osm);
1797      relation->flags = OSM_FLAG_NEW;
1798    
1799      /* attach to end of relation list */
1800      relation_t **lrelation = &osm->relation;
1801      while(*lrelation) lrelation = &(*lrelation)->next;
1802      *lrelation = relation;
1803    }
1804    
1805    
1806  void osm_way_delete(osm_t *osm, icon_t **icon,  void osm_way_delete(osm_t *osm, icon_t **icon,
1807                      way_t *way, gboolean permanently) {                      way_t *way, gboolean permanently) {
1808    
# Line 2125  void osm_way_delete(osm_t *osm, icon_t * Line 1866  void osm_way_delete(osm_t *osm, icon_t *
1866    }    }
1867  }  }
1868    
1869    void osm_relation_delete(osm_t *osm, relation_t *relation,
1870                             gboolean permanently) {
1871    
1872      /* new relations aren't stored on the server and are just */
1873      /* deleted permanently */
1874      if(relation->flags & OSM_FLAG_NEW) {
1875        printf("About to delete NEW relation #%ld -> force permanent delete\n",
1876               relation->id);
1877        permanently = TRUE;
1878      }
1879    
1880      /* the deletion of a relation doesn't affect the members as they */
1881      /* don't have any reference to the relation they are part of */
1882    
1883      if(!permanently) {
1884        printf("mark relation #%ld as deleted\n", relation->id);
1885        relation->flags |= OSM_FLAG_DELETED;
1886      } else {
1887        printf("permanently delete relation #%ld\n", relation->id);
1888    
1889        /* remove it from the chain */
1890        relation_t **crelation = &osm->relation;
1891        int found = 0;
1892    
1893        while(*crelation) {
1894          if(*crelation == relation) {
1895            found++;
1896            *crelation = (*crelation)->next;
1897    
1898            osm_relation_free(relation);
1899          } else
1900            crelation = &((*crelation)->next);
1901        }
1902        g_assert(found == 1);
1903      }
1904    }
1905    
1906  void osm_way_revert(way_t *way) {  void osm_way_revert(way_t *way) {
1907    node_chain_t *new = NULL;    node_chain_t *new = NULL;
1908    
# Line 2200  tag_t *osm_tags_copy(tag_t *src_tag, gbo Line 1978  tag_t *osm_tags_copy(tag_t *src_tag, gbo
1978    
1979    return new_tags;    return new_tags;
1980  }  }
1981    
1982    /* return plain text of type */
1983    char *osm_type_string(type_t type) {
1984      const struct { type_t type; char *name; } types[] = {
1985        { ILLEGAL,     "illegal" },
1986        { NODE,        "node" },
1987        { WAY,         "way" },
1988        { RELATION,    "relation" },
1989        { NODE_ID,     "node id" },
1990        { WAY_ID,      "way id" },
1991        { RELATION_ID, "relation id" },
1992        { 0, NULL }
1993      };
1994    
1995      int i;
1996      for(i=0;types[i].name;i++)
1997        if(type == types[i].type)
1998          return types[i].name;
1999    
2000      return NULL;
2001    }
2002    
2003    char *osm_object_string(type_t type, void *object) {
2004      char *type_str = osm_type_string(type);
2005    
2006      if(!object)
2007        return g_strdup_printf("%s #<invalid>", type_str);
2008    
2009      switch(type) {
2010      case ILLEGAL:
2011        return g_strdup_printf("%s #<unspec>", type_str);
2012        break;
2013      case NODE:
2014        return g_strdup_printf("%s #%ld", type_str, ((node_t*)object)->id);
2015        break;
2016      case WAY:
2017        return g_strdup_printf("%s #%ld", type_str, ((way_t*)object)->id);
2018        break;
2019      case RELATION:
2020        return g_strdup_printf("%s #%ld", type_str, ((relation_t*)object)->id);
2021        break;
2022      case NODE_ID:
2023      case WAY_ID:
2024      case RELATION_ID:
2025        return g_strdup_printf("%s #%ld", type_str, ((item_id_t)object));
2026        break;
2027      }
2028      return NULL;
2029    }
2030    
2031    char *osm_id_string(type_t type, void *object) {
2032      if(!object) return NULL;
2033    
2034      switch(type) {
2035      case ILLEGAL:
2036        return NULL;
2037        break;
2038      case NODE:
2039        return g_strdup_printf("#%ld", ((node_t*)object)->id);
2040        break;
2041      case WAY:
2042        return g_strdup_printf("#%ld", ((way_t*)object)->id);
2043        break;
2044      case RELATION:
2045        return g_strdup_printf("#%ld", ((relation_t*)object)->id);
2046        break;
2047      case NODE_ID:
2048      case WAY_ID:
2049      case RELATION_ID:
2050        return g_strdup_printf("#%ld", ((item_id_t)object));
2051        break;
2052      }
2053      return NULL;
2054    }
2055    
2056    tag_t *osm_object_get_tags(type_t type, void *object) {
2057      if(!object) return NULL;
2058    
2059      switch(type) {
2060      case ILLEGAL:
2061        return NULL;
2062        break;
2063      case NODE:
2064        return ((node_t*)object)->tag;
2065        break;
2066      case WAY:
2067        return ((way_t*)object)->tag;
2068        break;
2069      case RELATION:
2070        return ((relation_t*)object)->tag;
2071        break;
2072      case NODE_ID:
2073      case WAY_ID:
2074      case RELATION_ID:
2075        return NULL;
2076        break;
2077      }
2078      return NULL;
2079    }
2080    
2081    
2082    gint osm_relation_members_num(relation_t *relation) {
2083      gint num = 0;
2084      member_t *member = relation->member;
2085      while(member) {
2086        num++;
2087        member = member->next;
2088      }
2089      return num;
2090    }
2091    
2092  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

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