source: trunk/ruleset.c @ 4

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

renderer redesigned

  • 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: 9.1 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
20#include <time.h>
21#include <expat.h>
22#include <stdio.h>
23#include <string.h>
24
25#include "list.h"
26#include "strlist.h"
27#include "main.h"
28#include "ruleset.h"
29
30#define BUFFSIZE 1024
31#define MAXDEPTH 20
32#define MAXSTACK 20
33
34// External Vars
35extern int      debug;
36extern strList  *keyStrings;
37extern strList  *valStrings;
38
39// Pointers to work with
40cfgRule     *currentRule[MAXDEPTH];
41cfgRule     *closeRule[MAXDEPTH];
42char        **stringStack;
43
44// Counts
45int     cntCfgRule = 0;
46
47/**
48 * cfgStartElement:
49 * @userdata:  Void
50 * @name:  The element name
51 * @attributes: The element attribs
52 *
53 * called when the start of an element has been detected.
54 */
55static void XMLCALL
56cfgStartElement(void *userData, const char *name, const char **atts) {
57    cfgRules *ruleset = (cfgRules *)userData;
58    if (debug > 1)
59        fprintf(stdout,"cfgStartElement\n");
60
61    // Parsing Rules
62    if (strcmp((char *) name, "rules") == 0) {
63        // Init Ruleset
64        ruleset = malloc(sizeof(cfgRules));
65        ruleset->data = NULL;
66        ruleset->scale=1;
67        ruleset->rule = NULL;
68       
69        while (*atts != NULL) {
70            if(strcmp((char *) *(atts), "data") == 0) {
71                size_t c = strlen((char *) *(atts +1)) +1;
72                ruleset->data = malloc(c);
73                strncpy((char *) ruleset->data, (char *) *(atts +1), c);
74            } else if(strcmp((char *) *(atts), "scale") == 0) {
75                sscanf((char *) *(atts +1),"%f",&ruleset->scale);
76            }
77            atts+=2;
78        }
79    }
80    // Parsing Rule
81    else if (strcmp(name, "rule") == 0) {
82        ruleset->cntRule++;
83        ruleset->depth++;
84       
85        // Create Rule
86        cfgRule *new, *rulebuf, *rulebuf2;
87        new = malloc(sizeof(cfgRule));
88        new->next = NULL;
89        new->type = 0;
90        new->sub = NULL;
91        new->nsub = NULL;
92
93        char *buf, *buf2;
94        stringStack = malloc(MAXSTACK*sizeof(char *));
95        int c;
96       
97#ifdef DEBUG       
98        new->d = ruleset->depth;
99       
100        int h;
101        for(h=0;h<ruleset->depth;h++){
102            fprintf(stdout,"-");
103        }
104        fprintf(stdout,"rule\n");
105#endif       
106       
107        // Populate Rule
108        while (*atts != NULL) {
109            if(strcmp((char *) *(atts), "e") == 0) {
110                if(strstr((char *) *(atts +1),"way") != NULL)
111                    new->type |= WAY;
112                if(strstr((char *) *(atts +1),"node") != NULL)
113                    new->type |= NODE;
114            } else if(strcmp((char *) *(atts), "k") == 0) {
115                buf2 = strdup((char *) *(atts +1));
116                c = 0;
117                while((buf = strsep(&buf2, "|")) != NULL) {
118                     *(stringStack+c) = malloc(strlen(buf)+1);
119                    strncpy((char *) *(stringStack+c),buf,strlen(buf)+1);
120                    c++;
121                }
122                new->key = malloc((c+1)*sizeof(char *));
123                *(new->key+c) = NULL;
124                while(c--) {
125                    STRLIST_GET(keyStrings,*(stringStack+c),*(new->key+c));
126                    *(stringStack+c) = NULL;
127                }
128                free(buf2);
129            } else if(strcmp((char *) *(atts), "v") == 0) {
130                buf2 = strdup((char *) *(atts +1));
131                c = 0;
132                while((buf = strsep(&buf2, "|")) != NULL) {
133                    *(stringStack+c) = malloc(strlen(buf)+1);
134                    strncpy((char *) *(stringStack+c),buf,strlen(buf)+1);
135                    c++;
136                }
137                new->value = malloc((c+1)*sizeof(char *));
138                *(new->value+c) = NULL;
139                while(c--) {
140                    STRLIST_GET(valStrings,*(stringStack+c),*(new->value+c));
141                    *(stringStack+c) = NULL;
142                }
143                free(buf2);
144            }
145            atts+=2;
146        }
147       
148        free(stringStack);
149 
150        // Insert Rule
151        if(ruleset->rule == NULL)
152            ruleset->rule = new;
153       
154       
155        for(c=ruleset->depth;c< MAXDEPTH;c++) {
156            if (closeRule[c] == NULL)
157                break;
158               
159            rulebuf = closeRule[c];
160            while(rulebuf) {
161               rulebuf2 = rulebuf;
162               rulebuf = rulebuf->next;
163               rulebuf2->next = new;
164            }
165            closeRule[c] = NULL;
166        }
167       
168        new->next = closeRule[ruleset->depth];
169        closeRule[ruleset->depth] = new;
170       
171        for(c=ruleset->depth+1;c< MAXDEPTH;c++) {
172            currentRule[c] = NULL;
173        }
174       
175        if (currentRule[ruleset->depth] == NULL && ruleset->depth > 0) {
176            currentRule[ruleset->depth-1]->sub = new;
177        }
178       
179        currentRule[ruleset->depth] = new;       
180    }
181    // Parsing Else
182    else if (strcmp(name, "else") == 0) {
183        ruleset->cntElse++;
184        ruleset->depth++;
185       
186        // Create Else
187        cfgElse *new;
188        new = malloc(sizeof(cfgElse));
189       
190#ifdef DEBUG       
191        new->d = ruleset->depth;
192       
193        int h;
194        for(h=0;h<ruleset->depth;h++){
195            fprintf(stdout,"-");
196        }
197        fprintf(stdout,"else\n");
198#endif       
199       
200        // Insert Else
201        if (currentRule[ruleset->depth] != NULL) {
202            currentRule[ruleset->depth]->nsub = new;
203        }
204    }
205    // Parsing Polygone, etc.
206    else if (
207        strcmp(name, "polygone") == 0 ||
208        strcmp(name, "line") == 0
209    ) {
210        // Create Draw
211        cfgDraw *new;
212        new = malloc(sizeof(cfgDraw));     
213       
214        // Populate Draw
215        if (strcmp(name, "polygone") == 0)
216            new->type = POLYGONE;
217        else if (strcmp(name, "line") == 0)
218            new->type = LINE; 
219       
220        while (*atts != NULL) {
221            if(strcmp((char *) *(atts), "color") == 0) {
222                sscanf((char *) *(atts+1),"%f,%f,%f",&new->color[0],
223                            &new->color[1],&new->color[2]);
224            } else if(strcmp((char *) *(atts), "width") == 0) {
225                sscanf((char *) *(atts+1),"%hi",&new->width);
226            }
227            atts+=2;
228        }
229       
230        // Insert Draw
231        LL_APPEND(new,currentRule[ruleset->depth]->draw);
232    }
233}
234
235/**
236 * cfgEndElement:
237 * @userData:  Void
238 * @name:  The element name
239 *
240 * called when the end of an element has been detected.
241 */
242static void XMLCALL
243cfgEndElement(void *userData, const char *name) {
244    cfgRules *ruleset = (cfgRules *)userData;
245    if (debug > 1)
246        fprintf(stdout,"cfgEndElement\n");
247    if (strcmp(name, "rule") == 0) {
248        ruleset->depth--;
249    } else if (strcmp(name, "else") == 0) {
250        ruleset->depth--;
251    }
252}
253
254/**
255 * rulesetRead
256 */
257cfgRules* rulesetRead(char *filename) {
258    if (debug > 1)
259        fprintf(stdout,"rulesetRead\n");
260   
261    // Local Vars
262    int         len;
263    int         done;
264    char        *buf;
265    cfgRules    *ruleset = NULL;   
266   
267    // NULL rule stack
268    for (len=0;len<MAXDEPTH;len++) {
269        currentRule[len] = NULL;
270        closeRule[len] = NULL;
271    }
272   
273    // Open file
274    FILE *fd = fopen(filename,"r");
275    if(fd == NULL) {
276        fprintf(stderr,"Error: Can't open file \"%s\"\n",filename);
277        return NULL;
278    }
279   
280    ruleset = malloc(sizeof(cfgRules));
281    ruleset->depth = -1;
282    ruleset->cntRule = 0;
283    ruleset->cntElse = 0;
284   
285    long start = (long)clock();
286   
287    // Create XML Parser
288    XML_Parser parser = XML_ParserCreate(NULL);
289    XML_SetElementHandler(parser, cfgStartElement, cfgEndElement);
290    XML_SetUserData(parser, ruleset);
291   
292    // Create Buffer
293    buf = malloc(BUFFSIZE*sizeof(char));
294   
295    // Looping over XML
296    while(!feof(fd)) {
297         len = (int)fread(buf, 1, BUFFSIZE, fd);
298         if (ferror(fd)) {
299            fprintf(stderr, "Read error\n");
300            return NULL;;
301        }
302        done = len < sizeof(buf);
303        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
304            fprintf(stderr, "Parse error at line %iu:\n%s\n",
305                (int) XML_GetCurrentLineNumber(parser),
306                XML_ErrorString(XML_GetErrorCode(parser)));
307            exit(-1);
308        }       
309    }
310   
311    // Cleaning Memory
312    XML_ParserFree(parser);
313    free(buf);
314    fclose(fd);
315   
316    if (debug > 0)
317        fprintf(stdout," Ruleset parsing done. (%i/%i) [%fs]\n",
318                ruleset->cntRule, ruleset->cntElse,
319                ((long)clock()-start)/(double)CLOCKS_PER_SEC);   
320   
321    return(ruleset);
322}
Note: See TracBrowser for help on using the repository browser.