source: trunk/ruleset.c @ 7

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

bugfix and updates

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