source: trunk/osm05.c @ 38

Last change on this file since 38 was 38, checked in by marius, 6 years ago

free to g_free in new added free

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Date Author Id Revision HeadURL"
  • Property svn:mime-type set to text/plain
File size: 11.8 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 "main.h"
29#include "osm05.h"
30
31#define BUFFSIZE 1024
32
33// External Vars
34extern memphisOpt   *opts;
35GTree               *keyStrings;
36GTree               *valStrings;
37
38// Pointers to work with
39osmTag      *cTag = NULL;
40osmNode     *cNode = NULL;
41osmWay      *cWay = NULL;
42
43// Counts
44int     cntTag = 0;
45int     cntNd = 0;
46
47/**
48 * osmStartElement:
49 * @userdata:  Void
50 * @name:  The element name
51 * @atts: The element attribs
52 *
53 * called when the start of an element has been detected.
54 */
55static void XMLCALL
56osmStartElement(void *userData, const char *name, const char **atts) {
57    osmFile *osm = (osmFile *) userData;
58     if (opts->debug > 1)
59        fprintf(stdout,"osm05startElement\n");
60    // Parsing Bounds
61    if (strncmp((char *) name, "bounds", 6) == 0) {
62        if (opts->debug > 1)
63            fprintf(stdout,"Parsing Bounds\n");
64        while (*atts != NULL) {
65            if(strcmp((char *) *(atts), "minlat" ) == 0) {
66                sscanf((char *) *(atts+1),"%f",&osm->minlat);
67            } else if(strcmp((char *) *(atts), "minlon") == 0) {
68                sscanf((char *) *(atts+1),"%f",&osm->minlon);
69            } else if(strcmp((char *) *(atts), "maxlat") == 0) {
70                sscanf((char *) *(atts+1),"%f",&osm->maxlat);
71            } else if(strcmp((char *) *(atts), "maxlon") == 0) {
72                sscanf((char *) *(atts+1),"%f",&osm->maxlon);
73            }
74            atts+=2;
75        }
76    }
77    // Parsing Node
78    else if (strncmp((char *) name, "node", 4) == 0) {
79        if (opts->debug > 1)
80            fprintf(stdout,"Parsing Node\n");
81        cNode = g_new(osmNode, 1);
82        while (*atts != NULL) {
83            if(strcmp((char *) *(atts), "id") == 0) {
84                sscanf((char *) *(atts+1),"%i",&cNode->id);
85            } else if(strcmp((char *) *(atts), "lat") == 0) {
86                sscanf((char *) *(atts+1),"%f",&cNode->lat);
87            } else if(strcmp((char *) *(atts), "lon") == 0) {
88                sscanf((char *) *(atts+1),"%f",&cNode->lon);
89            }
90            atts+=2;
91        }
92
93        cNode->tag = NULL;
94        cNode->layer = 0;
95
96        // Insert Node
97        osm->nodecnt++;
98        g_hash_table_insert(osm->nodeidx, &cNode->id, cNode);
99        LL_PREPEND(cNode,osm->nodes);
100
101        if (opts->debug > 1)
102            fprintf(stdout,"NODE: %i %f %f\n", cNode->id, cNode->lat, cNode->lon);
103    }
104    // Parsing Tags
105    else if (strncmp((char *) name, "tag", 4) == 0) {
106        if (opts->debug > 1)
107            fprintf(stdout,"Parsing Tag\n");
108        cTag = g_new(osmTag, 1);
109        while (*atts != NULL) {
110            if(strncmp((char *) *(atts), "k", 1) == 0) {
111                if(strcmp((char *) *(atts+1), "created_by") == 0) {
112                    g_free(cTag);
113                    cTag = NULL;
114                    return;
115                } else if(strncmp((char *) *(atts+1), "source", 6) == 0) {
116                    g_free(cTag);
117                    cTag = NULL;
118                    return;
119                }
120                cTag->key = g_tree_lookup(keyStrings, (char *) *(atts+1));
121                if(cTag->key == NULL) {
122                    cTag->key = g_strdup((char *) *(atts+1));
123                    g_tree_insert(keyStrings, cTag->key, cTag->key);
124                }
125            } else if(strncmp((char *) *(atts), "v", 1) == 0) {
126                if(strcmp(cTag->key, "layer") == 0) {
127                    g_free(cTag);
128                    cTag = NULL;
129                    if (cNode)
130                        sscanf((char *) *(atts+1),"%hi",& cNode->layer);
131                    if (cWay)
132                        sscanf((char *) *(atts+1),"%hi",& cWay->layer);
133                    return;
134                } else if(strcmp(cTag->key, "name") == 0) {
135                    g_free(cTag);
136                    cTag = NULL;
137                    if (cWay) {
138                        cWay->name = g_tree_lookup(valStrings, (char *) *(atts+1));
139                        if(cWay->name == NULL) {
140                            cWay->name = g_strdup((char *) *(atts+1));
141                            g_tree_insert(valStrings, cWay->name, cWay->name);
142                        }
143                    }
144                    return;
145                }
146                cTag->value = g_tree_lookup(valStrings, (char *) *(atts+1));
147                if(cTag->value == NULL) {
148                    cTag->value = g_strdup((char *) *(atts+1));
149                    g_tree_insert(valStrings, cTag->value, cTag->value);
150                }
151            }
152            atts+=2;
153        }
154       
155        if (opts->debug > 1)
156            fprintf(stdout,"Tag: %s => %s\n", cTag->key, cTag->value);
157
158        cntTag++;
159        if (cNode)
160            LL_INSERT_KEY(cTag,cNode->tag);
161        else if (cWay)
162            LL_INSERT_KEY(cTag,cWay->tag);
163        else
164            g_free(cTag);
165
166        cTag = NULL;
167    }
168    // Parsing Way
169    else if (strncmp((char *) name, "way", 3) == 0) {
170        if (opts->debug > 1)
171            fprintf(stdout,"Parsing Way\n");
172        cWay = g_new(osmWay, 1);
173        while (*atts != NULL) {
174            if(strncmp((char *) *(atts), "id", 2) == 0) {
175                sscanf((char *) *(atts+1),"%i",&cWay->id);
176                break;
177            }
178            atts+=2;
179     }
180
181        cWay->tag = NULL;
182        cWay->nd = NULL;
183        cWay->name = NULL;
184        cWay->layer = 0;
185
186        // Insert Way
187        osm->waycnt++;
188        LL_PREPEND(cWay,osm->ways);
189
190        if (opts->debug > 1)
191            fprintf(stdout,"WAY(%i)\n", cWay->id);
192    }
193    // Parsing WayNode
194    else if (strncmp((char *) name, "nd", 2) == 0) {
195        if (opts->debug > 1)
196            fprintf(stdout,"Parsing Nd\n");
197        int ref = 0;
198        while (*atts != NULL) {
199            if(strncmp((char *) *(atts), "ref", 2) == 0) {
200                sscanf((char *) *(atts+1),"%i",&ref);
201                break;
202            }
203            atts+=2;
204        }
205
206        if (ref) {
207            cntNd++;
208            osmNode *n;
209           
210            n = g_hash_table_lookup(osm->nodeidx, &ref); /* TODO check return value */
211
212            // Insert WayNode
213            cWay->nd = g_slist_prepend(cWay->nd, n);
214
215            if (opts->debug > 1)
216                fprintf(stdout," ND( %f %f )\n", n->lat, n->lon);
217
218            cNode=NULL;
219        }
220    }
221}
222
223
224/**
225 * osmEndElement:
226 * @userData:  Void
227 * @name:  The element name
228 *
229 * called when the end of an element has been detected.
230 */
231static void XMLCALL
232osmEndElement(void *userData, const char *name) {
233    if (opts->debug > 1)
234        fprintf(stdout,"osm05endElement\n");
235    if (strncmp((char *) name, "node", 4) == 0) {
236        cNode = NULL;
237    } else if (strncmp((char *) name, "way", 3) == 0) {
238        if (cWay->nd != NULL)
239            cWay->nd = g_slist_reverse(cWay->nd);
240        cWay = NULL;
241    }
242}
243
244/**
245 * rulesetRead
246 */
247osmFile* osmRead(char *filename) {
248    if (opts->debug > 1)
249        fprintf(stdout,"osmRead\n");
250
251    // Init vars
252    cntTag = 0;
253    cntNd = 0;
254
255    // Local Vars
256    GTimer *tOsmRead = g_timer_new();
257    unsigned int size;
258    unsigned int read = 0;
259    struct stat filestat;
260    int len;
261    int done;
262    char *buf;
263    osmFile *osm = NULL;
264   
265    // Test file
266    if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
267        fprintf(stderr,"Error: \"%s\" is not a file.\n",filename);
268        return NULL;
269    }
270   
271    g_stat(filename, &filestat);
272    size = (int) filestat.st_size;
273
274    // Open file
275    FILE *fd = fopen(filename,"r");
276    if(fd == NULL) {
277        fprintf(stderr,"Error: Can't open file \"%s\"\n",filename);
278        return NULL;
279    }
280
281    osm = g_new(osmFile, 1);
282    osm->nodes = NULL;
283    osm->nodeidx = g_hash_table_new(g_int_hash, g_int_equal);
284    osm->nodecnt = 0;
285    osm->ways = NULL;
286    osm->waycnt = 0;
287    osm->minlon = -190;
288    osm->minlat = -190;
289    osm->maxlon = -190;
290    osm->maxlat = -190;
291
292    if (opts->debug > 0) {
293        fprintf(stdout," OSM parsing   0%%");
294        fflush(stdout);
295    }
296
297    // Create XML Parser
298    XML_Parser parser = XML_ParserCreate(NULL);
299    XML_SetElementHandler(parser, osmStartElement, osmEndElement);
300    XML_SetUserData(parser, osm);
301
302    // Create Buffer
303    buf = g_malloc(BUFFSIZE*sizeof(char));
304
305    // Looping over XML
306    while(!feof(fd)) {
307        len = (int)fread(buf, 1, BUFFSIZE, fd);
308        if (ferror(fd)) {
309            fprintf(stderr, "Read error\n");
310            return NULL;;
311        }
312        read += len;
313        if (opts->debug > 0) {
314            fprintf(stdout,"\r OSM parsing % 3i%%", (int)((read*100)/size));
315            fflush(stdout);
316        }
317        done = len < sizeof(buf);
318        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
319            fprintf(stderr, "Parse error at line %iu:\n%s\n",
320                (int) XML_GetCurrentLineNumber(parser),
321                XML_ErrorString(XML_GetErrorCode(parser)));
322            exit(-1);
323        }
324    }
325
326    // Cleaning Memory
327    XML_ParserFree(parser);
328    g_free(buf);
329    fclose(fd);
330
331    // No bounds set
332    if(osm->minlon == -190 || osm->minlat == -190 ||
333       osm->maxlon == -190 || osm->maxlat == -190) {
334       
335        osm->minlon = 360.0;
336        osm->minlat = 180.0;
337        osm->maxlon = -360.0;
338        osm->maxlat = -180.0;
339
340        osmNode *node;
341        LIST_FOREACH(node, osm->nodes) {
342            if(node->lon < osm->minlon)
343                osm->minlon = node->lon;
344            if(node->lat < osm->minlat)
345                osm->minlat = node->lat;
346            if(node->lon > osm->maxlon)
347                osm->maxlon = node->lon;
348            if(node->lat > osm->maxlat)
349                osm->maxlat = node->lat;
350        }
351    }
352
353    g_hash_table_destroy(osm->nodeidx);
354   
355    if (opts->debug > 0)
356        fprintf(stdout,"\r OSM parsing done. (%i/%i/%i/%i) [%fs]\n",
357                osm->nodecnt, osm->waycnt, cntTag, cntNd,
358                g_timer_elapsed(tOsmRead,NULL));
359   
360    g_timer_destroy(tOsmRead);
361
362    return(osm);
363}
364
365void osmFree(osmFile *osm) {
366    osmWay *way, *lway;
367    osmNode *node, *lnode;
368    osmTag *tag, *ltag;
369    for(way=osm->ways,lway=NULL;way;lway=way,way=way->next) {
370        g_slist_free(way->nd);
371        if(way->name)
372            g_tree_replace(valStrings, way->name, way->name);
373        for(tag=way->tag,ltag=NULL;tag;ltag=tag,tag=tag->next) {
374            g_tree_replace(keyStrings, tag->key, tag->key);
375            g_tree_replace(valStrings, tag->value, tag->value);
376            if(ltag)
377                g_free(ltag);
378        }
379        if(ltag)
380            g_free(ltag);
381        if(lway)
382            g_free(lway);
383    }
384    g_free(lway);
385   
386    for(node=osm->nodes,lnode=NULL;node;lnode=node,node=node->next) {
387        for(tag=node->tag,ltag=NULL;tag;ltag=tag,tag=tag->next) {
388            g_tree_replace(keyStrings, tag->key, tag->key);
389            g_tree_replace(valStrings, tag->value, tag->value);
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.