source: trunk/osm05.c @ 57

Last change on this file since 57 was 57, checked in by andy, 6 years ago

Check hashtable lookup return value
This case only occurs if the data is inconsistent.

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Date Author Id Revision HeadURL"
  • Property svn:mime-type set to text/x-csrc
File size: 11.2 KB
Line 
1/*
2 * Memphis - Cairo Rederer for OSM in C
3 * Copyright (C) 2008  <marius.rieder@durchmesser.ch>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19#include <glib.h>
20#include <glib/gstdio.h>
21
22#include <time.h>
23#include <expat.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "list.h"
28#include "mlib.h"
29#include "main.h"
30#include "osm05.h"
31
32#define BUFFSIZE 1024
33
34// External Vars
35extern memphisOpt   *opts;
36extern GStringChunk *stringChunk;
37extern GTree        *stringTree;
38
39// Pointers to work with
40osmTag      *cTag = NULL;
41osmNode     *cNode = NULL;
42osmWay      *cWay = NULL;
43
44// Counts
45int     cntTag = 0;
46int     cntNd = 0;
47
48/**
49 * osmStartElement:
50 * @userdata:  Void
51 * @name:  The element name
52 * @atts: The element attribs
53 *
54 * called when the start of an element has been detected.
55 */
56static void XMLCALL
57osmStartElement(void *userData, const char *name, const char **atts) {
58    osmFile *osm = (osmFile *) userData;
59     if (opts->debug > 1)
60        fprintf(stdout,"osm05startElement\n");
61    // Parsing Bounds
62    if (strncmp((char *) name, "bounds", 6) == 0) {
63        if (opts->debug > 1)
64            fprintf(stdout,"Parsing Bounds\n");
65        while (*atts != NULL) {
66            if(strcmp((char *) *(atts), "minlat" ) == 0) {
67                sscanf((char *) *(atts+1),"%f",&osm->minlat);
68            } else if(strcmp((char *) *(atts), "minlon") == 0) {
69                sscanf((char *) *(atts+1),"%f",&osm->minlon);
70            } else if(strcmp((char *) *(atts), "maxlat") == 0) {
71                sscanf((char *) *(atts+1),"%f",&osm->maxlat);
72            } else if(strcmp((char *) *(atts), "maxlon") == 0) {
73                sscanf((char *) *(atts+1),"%f",&osm->maxlon);
74            }
75            atts+=2;
76        }
77    }
78    // Parsing Node
79    else if (strncmp((char *) name, "node", 4) == 0) {
80        if (opts->debug > 1)
81            fprintf(stdout,"Parsing Node\n");
82        cNode = g_new(osmNode, 1);
83        while (*atts != NULL) {
84            if(strcmp((char *) *(atts), "id") == 0) {
85                sscanf((char *) *(atts+1),"%i",&cNode->id);
86            } else if(strcmp((char *) *(atts), "lat") == 0) {
87                sscanf((char *) *(atts+1),"%f",&cNode->lat);
88            } else if(strcmp((char *) *(atts), "lon") == 0) {
89                sscanf((char *) *(atts+1),"%f",&cNode->lon);
90            }
91            atts+=2;
92        }
93
94        cNode->tag = NULL;
95        cNode->layer = 0;
96
97        // Insert Node
98        osm->nodecnt++;
99        g_hash_table_insert(osm->nodeidx, &cNode->id, cNode);
100        LL_PREPEND(cNode,osm->nodes);
101
102        if (opts->debug > 1)
103            fprintf(stdout,"NODE: %i %f %f\n", cNode->id, cNode->lat, cNode->lon);
104    }
105    // Parsing Tags
106    else if (strncmp((char *) name, "tag", 4) == 0) {
107        if (opts->debug > 1)
108            fprintf(stdout,"Parsing Tag\n");
109
110        if (!cNode && !cWay) // End if ther is nothing to add the tag to
111            return;
112           
113        char *k=NULL, *v=NULL;
114
115        while (*atts != NULL) {
116            if(strncmp((char *) *(atts), "k", 1) == 0) {
117                if(strcmp((char *) *(atts+1), "created_by") == 0) {
118                    return;
119                } else if(strncmp((char *) *(atts+1), "source", 6) == 0) {
120                    return;
121                }
122                k = (char *) *(atts+1);
123            } else if(strncmp((char *) *(atts), "v", 1) == 0) {
124                if(strcmp(k, "layer") == 0) {
125                    if (cNode)
126                        sscanf((char *) *(atts+1),"%hi",& cNode->layer);
127                    else if (cWay)
128                        sscanf((char *) *(atts+1),"%hi",& cWay->layer);
129                    return;
130                } else if(strcmp(k, "name") == 0) {
131                    if (cWay) {
132                        cWay->name = m_string_chunk_get(stringChunk, stringTree,
133                                                        (char *) *(atts+1));
134                    }
135                    return;
136                }
137                v = (char *) *(atts+1);
138            }
139            atts += 2;
140        }
141       
142        cTag = g_new(osmTag, 1);
143        cTag->key = m_string_chunk_get(stringChunk, stringTree, k);
144        cTag->value = m_string_chunk_get(stringChunk, stringTree, v);
145       
146        if (opts->debug > 1)
147            fprintf(stdout,"Tag: %s => %s\n", cTag->key, cTag->value);
148
149        cntTag++;
150        if (cNode)
151            LL_INSERT_KEY(cTag,cNode->tag);
152        else if (cWay)
153            LL_INSERT_KEY(cTag,cWay->tag);
154
155        cTag = NULL;
156    }
157    // Parsing Way
158    else if (strncmp((char *) name, "way", 3) == 0) {
159        if (opts->debug > 1)
160            fprintf(stdout,"Parsing Way\n");
161        cWay = g_new(osmWay, 1);
162        while (*atts != NULL) {
163            if(strncmp((char *) *(atts), "id", 2) == 0) {
164                sscanf((char *) *(atts+1),"%i",&cWay->id);
165                break;
166            }
167            atts+=2;
168        }
169
170        cWay->tag = NULL;
171        cWay->nd = NULL;
172        cWay->name = NULL;
173        cWay->layer = 0;
174
175        // Insert Way
176        osm->waycnt++;
177        LL_PREPEND(cWay,osm->ways);
178
179        if (opts->debug > 1)
180            fprintf(stdout,"WAY(%i)\n", cWay->id);
181    }
182    // Parsing WayNode
183    else if (strncmp((char *) name, "nd", 2) == 0) {
184        if (opts->debug > 1)
185            fprintf(stdout,"Parsing Nd\n");
186        int ref = 0;
187        while (*atts != NULL) {
188            if(strncmp((char *) *(atts), "ref", 2) == 0) {
189                sscanf((char *) *(atts+1),"%i",&ref);
190                break;
191            }
192            atts+=2;
193        }
194
195        if (ref) {
196            cntNd++;
197            osmNode *n;
198           
199            n = g_hash_table_lookup(osm->nodeidx, &ref);
200            if (!n) {
201                g_warning("No node with reference %d found!\n", ref);
202                return;
203            }
204
205            // Insert WayNode
206            cWay->nd = g_slist_prepend(cWay->nd, n);
207
208            if (opts->debug > 1)
209                fprintf(stdout," ND( %f %f )\n", n->lat, n->lon);
210
211            cNode=NULL;
212        }
213    }
214}
215
216
217/**
218 * osmEndElement:
219 * @userData:  Void
220 * @name:  The element name
221 *
222 * called when the end of an element has been detected.
223 */
224static void XMLCALL
225osmEndElement(void *userData, const char *name) {
226    if (opts->debug > 1)
227        fprintf(stdout,"osm05endElement\n");
228    if (strncmp((char *) name, "node", 4) == 0) {
229        cNode = NULL;
230    } else if (strncmp((char *) name, "way", 3) == 0) {
231        if (cWay->nd != NULL)
232            cWay->nd = g_slist_reverse(cWay->nd);
233        cWay = NULL;
234    }
235}
236
237/**
238 * rulesetRead
239 */
240osmFile* osmRead(char *filename) {
241    if (opts->debug > 1)
242        fprintf(stdout,"osmRead\n");
243
244    // Init vars
245    cntTag = 0;
246    cntNd = 0;
247
248    // Local Vars
249    GTimer *tOsmRead = g_timer_new();
250    unsigned int size;
251    unsigned int read = 0;
252    struct stat filestat;
253    int len;
254    int done;
255    char *buf;
256    osmFile *osm = NULL;
257   
258    // Test file
259    if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
260        fprintf(stderr,"Error: \"%s\" is not a file.\n",filename);
261        return NULL;
262    }
263   
264    g_stat(filename, &filestat);
265    size = (int) filestat.st_size;
266
267    // Open file
268    FILE *fd = fopen(filename,"r");
269    if(fd == NULL) {
270        fprintf(stderr,"Error: Can't open file \"%s\"\n",filename);
271        return NULL;
272    }
273
274    osm = g_new(osmFile, 1);
275    osm->nodes = NULL;
276    osm->nodeidx = g_hash_table_new(g_int_hash, g_int_equal);
277    osm->nodecnt = 0;
278    osm->ways = NULL;
279    osm->waycnt = 0;
280    osm->minlon = -190;
281    osm->minlat = -190;
282    osm->maxlon = -190;
283    osm->maxlat = -190;
284
285    if (opts->debug > 0) {
286        fprintf(stdout," OSM parsing   0%%");
287        fflush(stdout);
288    }
289
290    // Create XML Parser
291    XML_Parser parser = XML_ParserCreate(NULL);
292    XML_SetElementHandler(parser, osmStartElement, osmEndElement);
293    XML_SetUserData(parser, osm);
294
295    // Create Buffer
296    buf = g_malloc(BUFFSIZE*sizeof(char));
297
298    // Looping over XML
299    while(!feof(fd)) {
300        len = (int)fread(buf, 1, BUFFSIZE, fd);
301        if (ferror(fd)) {
302            fprintf(stderr, "Read error\n");
303            return NULL;;
304        }
305        read += len;
306        if (opts->debug > 0) {
307            fprintf(stdout,"\r OSM parsing % 3i%%", (int)((read*100)/size));
308            fflush(stdout);
309        }
310        done = len < sizeof(buf);
311        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
312            fprintf(stderr, "Parse error at line %iu:\n%s\n",
313                (int) XML_GetCurrentLineNumber(parser),
314                XML_ErrorString(XML_GetErrorCode(parser)));
315            exit(-1);
316        }
317    }
318
319    // Cleaning Memory
320    XML_ParserFree(parser);
321    g_free(buf);
322    fclose(fd);
323
324    // No bounds set
325    if(osm->minlon == -190 || osm->minlat == -190 ||
326       osm->maxlon == -190 || osm->maxlat == -190) {
327       
328        osm->minlon = 360.0;
329        osm->minlat = 180.0;
330        osm->maxlon = -360.0;
331        osm->maxlat = -180.0;
332
333        osmNode *node;
334        LIST_FOREACH(node, osm->nodes) {
335            if(node->lon < osm->minlon)
336                osm->minlon = node->lon;
337            if(node->lat < osm->minlat)
338                osm->minlat = node->lat;
339            if(node->lon > osm->maxlon)
340                osm->maxlon = node->lon;
341            if(node->lat > osm->maxlat)
342                osm->maxlat = node->lat;
343        }
344    }
345
346    g_hash_table_destroy(osm->nodeidx);
347    osm->nodeidx=NULL;
348   
349    if (opts->debug > 0)
350        fprintf(stdout,"\r OSM parsing done. (%i/%i/%i/%i) [%fs]\n",
351                osm->nodecnt, osm->waycnt, cntTag, cntNd,
352                g_timer_elapsed(tOsmRead,NULL));
353   
354    g_timer_destroy(tOsmRead);
355
356    return(osm);
357}
358
359void osmFree(osmFile *osm) {
360    osmWay *way, *lway;
361    osmNode *node, *lnode;
362    osmTag *tag, *ltag;
363    for(way = osm->ways, lway = NULL;
364        way != NULL;
365        lway = way, way = way->next)
366    {
367        g_slist_free(way->nd);
368        for(tag = way->tag, ltag = NULL;
369            tag != NULL;
370            ltag = tag, tag = tag->next)
371        {
372            if(ltag)
373                g_free(ltag);
374        }
375        if(ltag)
376            g_free(ltag);
377        if(lway)
378            g_free(lway);
379    }
380    g_free(lway);
381   
382    for(node = osm->nodes, lnode = NULL;
383        node != NULL;
384        lnode = node, node = node->next)
385    {
386        for(tag = node->tag, ltag = NULL;
387            tag != NULL;
388            ltag = tag, tag = tag->next)
389        {
390            if(ltag)
391                g_free(ltag);
392        }
393        if(ltag)
394            g_free(ltag);
395        if(lnode)
396            g_free(lnode);
397    }
398    g_free(lnode);
399    g_free(osm);
400};
401
402/*
403 * vim: expandtab shiftwidth=4 tabstop=4:
404 */
405
Note: See TracBrowser for help on using the repository browser.