source: trunk/ruleset.c @ 16

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

start using glib

  • 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 <glib.h>
20#include <time.h>
21#include <expat.h>
22#include <stdio.h>
23#include <string.h>
24
25#include "main.h"
26#include "list.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 GTree        *keyStrings;
36extern GTree        *valStrings;
37extern GTree        *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        new->draw = NULL;
88        new->ndraw = NULL;
89
90        char *buf, *buf2;
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    int         len;
238    int         done;
239    char        *buf;
240    cfgRules    *ruleset = NULL;
241
242    // NULL rule stack
243    for (len=0;len<MAXDEPTH;len++) {
244        ruleStack[len] = NULL;
245    }
246
247    // Open file
248    FILE *fd = fopen(filename,"r");
249    if(fd == NULL) {
250        fprintf(stderr,"Error: Can't open file \"%s\"\n",filename);
251        return NULL;
252    }
253
254    ruleset = malloc(sizeof(cfgRules));
255    ruleset->depth = -1;
256    ruleset->cntRule = 0;
257    ruleset->cntElse = 0;
258
259    if (opts->debug > 0) {
260        fprintf(stdout," Ruleset parsing");
261        fflush(stdout);
262    }
263
264    long start = (long)clock();
265
266    // Create XML Parser
267    XML_Parser parser = XML_ParserCreate(NULL);
268    XML_SetElementHandler(parser, cfgStartElement, cfgEndElement);
269
270    XML_SetUserData(parser, ruleset);
271
272    // Create Buffer
273    buf = malloc(BUFFSIZE*sizeof(char));
274
275    // Looping over XML
276    while(!feof(fd)) {
277         len = (int)fread(buf, 1, BUFFSIZE, fd);
278         if (ferror(fd)) {
279            fprintf(stderr, "Read error\n");
280            return NULL;;
281        }
282        done = len < sizeof(buf);
283        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
284            fprintf(stderr, "Parse error at line %iu:\n%s\n",
285                (int) XML_GetCurrentLineNumber(parser),
286                XML_ErrorString(XML_GetErrorCode(parser)));
287            exit(-1);
288        }
289    }
290
291    // Cleaning Memory
292    XML_ParserFree(parser);
293    free(buf);
294    fclose(fd);
295
296    if (opts->debug > 0)
297        fprintf(stdout," done. (%i/%i) [%fs]\n",
298                ruleset->cntRule, ruleset->cntElse,
299                ((long)clock()-start)/(double)CLOCKS_PER_SEC);
300
301    return(ruleset);
302}
303
304/*
305 * vim: expandtab shiftwidth=4 tabstop=4:
306 */
307
Note: See TracBrowser for help on using the repository browser.