source: trunk/ruleset.c @ 29

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

cosmetic changes in ruleset.c and make testRuleset working

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