source: trunk/ruleset.c @ 15

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

adding support for naming ways

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