Fix:core:Reduce debug output, use dbg() instead of printf.
[profile/ivi/navit.git] / navit / navit / map / textfile / textfile.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <glib.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <math.h>
26 #include "config.h"
27 #include "debug.h"
28 #include "plugin.h"
29 #include "projection.h"
30 #include "item.h"
31 #include "map.h"
32 #include "maptype.h"
33 #include "attr.h"
34 #include "transform.h"
35 #include "file.h"
36
37 #include "textfile.h"
38
39 static int map_id;
40
41 static void
42 remove_comment_line(char* line){
43         if (line==TEXTFILE_COMMENT_CHAR){
44                 line='\0';
45         }
46 }
47
48 static void
49 get_line(struct map_rect_priv *mr)
50 {
51         if(mr->f) {
52                 if (!mr->m->is_pipe) 
53                         mr->pos=ftell(mr->f);
54                 else
55                         mr->pos+=mr->lastlen;
56                 fgets(mr->line, TEXTFILE_LINE_SIZE, mr->f);
57                 dbg(1,"read textfile line: %s\n", mr->line);
58                 remove_comment_line(mr->line);
59                 mr->lastlen=strlen(mr->line)+1;
60                 if (strlen(mr->line) >= TEXTFILE_LINE_SIZE-1) 
61                         dbg(0, "line too long: %s\n", mr->line);
62         }
63 }
64
65 static void
66 map_destroy_textfile(struct map_priv *m)
67 {
68         g_free(m->filename);
69         if(m->charset) {
70                 g_free(m->charset);
71         }
72         g_free(m);
73 }
74
75 static void
76 textfile_coord_rewind(void *priv_data)
77 {
78 }
79
80 static int
81 parse_line(struct map_rect_priv *mr, int attr)
82 {
83         int pos;
84
85         pos=coord_parse(mr->line, projection_mg, &mr->c);
86         if (pos < strlen(mr->line) && attr) {
87                 strcpy(mr->attrs, mr->line+pos);
88         }
89         return pos;
90 }
91
92 static int
93 textfile_coord_get(void *priv_data, struct coord *c, int count)
94 {
95         struct map_rect_priv *mr=priv_data;
96         int ret=0;
97         dbg(1,"enter, count: %d\n",count);
98         while (count--) {
99                 if (mr->f && !feof(mr->f) && (!mr->item.id_hi || !mr->eoc) && parse_line(mr, mr->item.id_hi)) {
100                         *c=mr->c;
101                         dbg(1,"c=0x%x,0x%x\n", c->x, c->y);
102                         c++;
103                         ret++;          
104                         get_line(mr);
105                         if (mr->item.id_hi)
106                                 mr->eoc=1;
107                 } else {
108                         mr->more=0;
109                         break;
110                 }
111         }
112         return ret;
113 }
114
115 static void
116 textfile_attr_rewind(void *priv_data)
117 {
118         struct map_rect_priv *mr=priv_data;
119         mr->attr_pos=0;
120         mr->attr_last=attr_none;
121 }
122
123 static void
124 textfile_encode_attr(char *attr_val, enum attr_type attr_type, struct attr *attr)
125 {
126         if (attr_type >= attr_type_int_begin && attr_type <= attr_type_int_end) 
127                 attr->u.num=atoi(attr_val);
128         else
129                 attr->u.str=attr_val;
130 }
131
132 static int
133 textfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
134 {       
135         struct map_rect_priv *mr=priv_data;
136         char *str=NULL;
137         dbg(1,"mr=%p attrs='%s' ", mr, mr->attrs);
138         if (attr_type != mr->attr_last) {
139                 dbg(1,"reset attr_pos\n");
140                 mr->attr_pos=0;
141                 mr->attr_last=attr_type;
142         }
143         if (attr_type == attr_any) {
144                 dbg(1,"attr_any");
145                 if (attr_from_line(mr->attrs,NULL,&mr->attr_pos,mr->attr, mr->attr_name)) {
146                         attr_type=attr_from_name(mr->attr_name);
147                         dbg(1,"found attr '%s' 0x%x\n", mr->attr_name, attr_type);
148                         attr->type=attr_type;
149                         textfile_encode_attr(mr->attr, attr_type, attr);
150                         return 1;
151                 }
152         } else {
153                 str=attr_to_name(attr_type);
154                 dbg(1,"attr='%s' ",str);
155                 if (attr_from_line(mr->attrs,str,&mr->attr_pos,mr->attr, NULL)) {
156                         textfile_encode_attr(mr->attr, attr_type, attr);
157                         dbg(1,"found\n");
158                         return 1;
159                 }
160         }
161         dbg(1,"not found\n");
162         return 0;
163 }
164
165 static struct item_methods methods_textfile = {
166         textfile_coord_rewind,
167         textfile_coord_get,
168         textfile_attr_rewind,
169         textfile_attr_get,
170 };
171
172 static struct map_rect_priv *
173 map_rect_new_textfile(struct map_priv *map, struct map_selection *sel)
174 {
175         struct map_rect_priv *mr;
176
177         dbg(1,"enter\n");
178         mr=g_new0(struct map_rect_priv, 1);
179         mr->m=map;
180         mr->sel=sel;
181         if (map->flags & 1)
182                 mr->item.id_hi=1;
183         else
184                 mr->item.id_hi=0;
185         mr->item.id_lo=0;
186         mr->item.meth=&methods_textfile;
187         mr->item.priv_data=mr;
188         if (map->is_pipe) {
189 #ifdef HAVE_POPEN
190                 char *oargs,*args=g_strdup(map->filename),*sep=" ";
191                 enum layer_type lay;
192                 g_free(mr->args);
193                 while (sel) {
194                         oargs=args;
195                         args=g_strdup_printf("%s 0x%x 0x%x 0x%x 0x%x", oargs, sel->u.c_rect.lu.x, sel->u.c_rect.lu.y, sel->u.c_rect.rl.x, sel->u.c_rect.rl.y);
196                         g_free(oargs);
197                         for (lay=layer_town ; lay < layer_end ; lay++) {
198                                 oargs=args;
199                                 args=g_strdup_printf("%s%s%d", oargs, sep, sel->order);
200                                 g_free(oargs);
201                                 sep=",";
202                         }
203                         sel=sel->next;
204                 }
205                 dbg(1,"popen args %s\n", args);
206                 mr->args=args;
207                 mr->f=popen(mr->args, "r");
208                 mr->pos=0;
209                 mr->lastlen=0;
210 #else
211                 dbg(0,"unable to work with pipes %s\n",map->filename);
212 #endif 
213         } else {
214                 mr->f=fopen(map->filename, "r");
215         }
216         if(!mr->f) {
217                 dbg(0, "error opening textfile %s: %s\n",map->filename, strerror(errno));
218         }
219         get_line(mr);
220         return mr;
221 }
222
223
224 static void
225 map_rect_destroy_textfile(struct map_rect_priv *mr)
226 {
227         if (mr->f) {
228                 if (mr->m->is_pipe) {
229 #ifdef HAVE_POPEN
230                         pclose(mr->f);
231 #endif
232                 }
233                 else {
234                         fclose(mr->f);
235                 }
236         }
237         g_free(mr);
238 }
239
240 static struct item *
241 map_rect_get_item_textfile(struct map_rect_priv *mr)
242 {
243         char *p,type[TEXTFILE_LINE_SIZE];
244         dbg(1,"map_rect_get_item_textfile id_hi=%d line=%s", mr->item.id_hi, mr->line);
245         if (!mr->f) {
246                 return NULL;
247         }
248         while (mr->more) {
249                 struct coord c;
250                 textfile_coord_get(mr, &c, 1);
251         }
252         for(;;) {
253                 if (feof(mr->f)) {
254                         dbg(1,"map_rect_get_item_textfile: eof %d\n",mr->item.id_hi);
255                         if (mr->m->flags & 1) {
256                                 if (!mr->item.id_hi) 
257                                         return NULL;
258                                 mr->item.id_hi=0;
259                         } else {
260                                 if (mr->item.id_hi) 
261                                         return NULL;
262                                 mr->item.id_hi=1;
263                         }
264                         if (mr->m->is_pipe) {
265 #ifdef HAVE_POPEN
266                                 pclose(mr->f);
267                                 mr->f=popen(mr->args, "r");
268                                 mr->pos=0;
269                                 mr->lastlen=0;
270 #endif
271                         } else {
272                                 fseek(mr->f, 0, SEEK_SET);
273                                 clearerr(mr->f);
274                         }
275                         get_line(mr);
276                 }
277                 if ((p=strchr(mr->line,'\n'))) 
278                         *p='\0';
279                 if (mr->item.id_hi) {
280                         mr->attrs[0]='\0';
281                         if (!parse_line(mr, 1)) {
282                                 get_line(mr);
283                                 continue;
284                         }
285                         dbg(1,"map_rect_get_item_textfile: point found\n");
286                         mr->eoc=0;
287                         mr->item.id_lo=mr->pos;
288                 } else {
289                         if (parse_line(mr, 1)) {
290                                 get_line(mr);
291                                 continue;
292                         }
293                         dbg(1,"map_rect_get_item_textfile: line found\n");
294                         if (! mr->line[0]) {
295                                 get_line(mr);
296                                 continue;
297                         }
298                         mr->item.id_lo=mr->pos;
299                         strcpy(mr->attrs, mr->line);
300                         get_line(mr);
301                         dbg(1,"mr=%p attrs=%s\n", mr, mr->attrs);
302                 }
303                 dbg(1,"get_attrs %s\n", mr->attrs);
304                 if (attr_from_line(mr->attrs,"type",NULL,type,NULL)) {
305                         dbg(1,"type='%s'\n", type);
306                         mr->item.type=item_from_name(type);
307                         if (mr->item.type == type_none) 
308                                 dbg(0, "Warning: type '%s' unknown\n", type);
309                 } else {
310                         get_line(mr);
311                         continue;
312                 }
313                 mr->attr_last=attr_none;
314                 mr->more=1;
315                 dbg(1,"return attr='%s'\n", mr->attrs);
316                 return &mr->item;
317         }
318 }
319
320 static struct item *
321 map_rect_get_item_byid_textfile(struct map_rect_priv *mr, int id_hi, int id_lo)
322 {
323         if (mr->m->is_pipe) {
324 #ifndef _MSC_VER
325                 pclose(mr->f);
326                 mr->f=popen(mr->args, "r");
327                 mr->pos=0;
328                 mr->lastlen=0;
329 #endif /* _MSC_VER */
330         } else
331                 fseek(mr->f, id_lo, SEEK_SET);
332         get_line(mr);
333         mr->item.id_hi=id_hi;
334         return map_rect_get_item_textfile(mr);
335 }
336
337 static struct map_methods map_methods_textfile = {
338         projection_mg,
339         "iso8859-1",
340         map_destroy_textfile,
341         map_rect_new_textfile,
342         map_rect_destroy_textfile,
343         map_rect_get_item_textfile,
344         map_rect_get_item_byid_textfile,
345 };
346
347 static struct map_priv *
348 map_new_textfile(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
349 {
350         struct map_priv *m;
351         struct attr *data=attr_search(attrs, NULL, attr_data);
352         struct attr *charset=attr_search(attrs, NULL, attr_charset);
353         struct attr *flags=attr_search(attrs, NULL, attr_flags);
354         struct file_wordexp *wexp;
355         int len,is_pipe=0;
356         char *wdata;
357         char **wexp_data;
358         if (! data)
359                 return NULL;
360         dbg(1,"map_new_textfile %s\n", data->u.str);    
361         wdata=g_strdup(data->u.str);
362         len=strlen(wdata);
363         if (len && wdata[len-1] == '|') {
364                 wdata[len-1]='\0';
365                 is_pipe=1;
366         }
367         wexp=file_wordexp_new(wdata);
368         wexp_data=file_wordexp_get_array(wexp);
369         *meth=map_methods_textfile;
370
371         m=g_new0(struct map_priv, 1);
372         m->id=++map_id;
373         m->filename=g_strdup(wexp_data[0]);
374         m->is_pipe=is_pipe;
375         if (flags) 
376                 m->flags=flags->u.num;
377         dbg(1,"map_new_textfile %s %s\n", m->filename, wdata);
378         if (charset) {
379                 m->charset=g_strdup(charset->u.str);
380                 meth->charset=m->charset;
381         }
382         file_wordexp_destroy(wexp);
383         g_free(wdata);
384         return m;
385 }
386
387 void
388 plugin_init(void)
389 {
390         dbg(1,"textfile: plugin_init\n");
391         plugin_register_map_type("textfile", map_new_textfile);
392 }
393