source: trunk/ruleset.c @ 5

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

finisched reworking

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