/[zanavi_public1]/navit/navit/map/csv/csv.c
ZANavi

Contents of /navit/navit/map/csv/csv.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (hide annotations) (download)
Wed Mar 4 14:00:54 2015 UTC (9 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 16872 byte(s)
new market version, lots of fixes
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2011 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 <stdlib.h>
21     #include <glib.h>
22     #include <stdio.h>
23     #include <string.h>
24     #ifdef HAVE_UNISTD_H
25     #include <unistd.h>
26     #endif
27     #include <math.h>
28     #include "config.h"
29     #include "debug.h"
30     #include "plugin.h"
31     #include "projection.h"
32     #include "item.h"
33     #include "map.h"
34     #include "maptype.h"
35     #include "attr.h"
36     #include "transform.h"
37     #include "file.h"
38     #include "quadtree.h"
39    
40     #include "csv.h"
41    
42     static int map_id;
43    
44     //prototype
45     static int
46     csv_coord_set(void *priv_data, struct coord *c, int count, enum change_mode mode);
47     static struct item * csv_create_item(struct map_rect_priv *mr, enum item_type it_type);
48    
49     struct quadtree_data
50     {
51     struct item* item;
52     GList* attr_list;
53     };
54    
55     static void
56     save_map_csv(struct map_priv *m)
57     {
58     if(m->dirty) {
59     GList *res = NULL, *item_it;
60     char* filename = g_strdup_printf("%s.tmp",m->filename);
61     FILE* fp;
62     int ferr = 0;
63     char *csv_line = 0;
64     char *tmpstr = 0;
65     char *oldstr = 0;
66    
67     if( ! (fp=fopen(filename,"w+"))) {
68     dbg(1, "Error opening csv file to write new entries");
69     return;
70     }
71     //query the world
72     quadtree_find_rect_items(m->tree_root, -90, 90, -90, 90, &res);
73    
74     item_it = res;
75     while(item_it) {
76     int i;
77     enum attr_type *at = m->attr_types;
78     csv_line = g_strdup("");
79     tmpstr = g_strdup("");
80     for(i=0;i<m->attr_cnt;++i) {
81     if(at != m->attr_types) {
82     csv_line = g_strdup_printf("%s,",tmpstr);
83     }
84     g_free(tmpstr);
85     tmpstr = NULL;
86    
87     if(*at == attr_position_latitude) {
88     tmpstr = g_strdup_printf("%lf",((struct quadtree_item*)(item_it->data))->latitude);
89     }
90     else if(*at == attr_position_longitude) {
91     tmpstr = g_strdup_printf("%lf",((struct quadtree_item*)(item_it->data))->longitude);
92     }
93     else {
94     GList* attr_list = ((struct quadtree_data*)(((struct quadtree_item*)(item_it->data))->data))->attr_list;
95     GList* attr_it = attr_list;
96     struct attr* found_attr = NULL;
97     //search attributes
98     while(attr_it) {
99     if(((struct attr*)(attr_it->data))->type == *at) {
100     found_attr = attr_it->data;
101     break;
102     }
103     attr_it = g_list_next(attr_it);
104     }
105     if(found_attr) {
106     if(ATTR_IS_INT(*at)) {
107     tmpstr = g_strdup_printf("%d", found_attr->u.num);
108     }
109     else if(ATTR_IS_DOUBLE(*at)) {
110     tmpstr = g_strdup_printf("%lf", *found_attr->u.numd);
111     }
112     else if(ATTR_IS_STRING(*at)) {
113     tmpstr = g_strdup(found_attr->u.str);
114     }
115     }
116     else { //TODO handle this error
117     }
118     }
119     oldstr = csv_line;
120     csv_line = g_strdup_printf("%s%s",csv_line,tmpstr);
121     g_free(tmpstr);
122     g_free(oldstr);
123     tmpstr = csv_line;
124     ++at;
125     }
126     if(fprintf(fp,"%s\n", csv_line)<0) {
127     ferr = 1;
128     }
129     item_it = g_list_next(item_it);
130     tmpstr=g_strdup("");
131     }
132    
133     if(fclose(fp)) {
134     ferr = 1;
135     }
136    
137     if(! ferr) {
138     unlink(m->filename);
139     rename(filename,m->filename);
140     }
141     g_free(filename);
142     m->dirty = 0;
143     }
144     }
145    
146     static const int zoom_max = 18;
147    
148     static void
149     map_destroy_csv(struct map_priv *m)
150     {
151     dbg(1,"map_destroy_csv\n");
152     //save if changed
153     save_map_csv(m);
154     g_hash_table_destroy(m->item_hash);
155     g_hash_table_destroy(m->qitem_hash);
156     quadtree_destroy(m->tree_root);
157     g_free(m->filename);
158     g_free(m->attr_types);
159     g_free(m);
160     }
161    
162     static void
163     csv_coord_rewind(void *priv_data)
164     {
165     }
166    
167     static int
168     csv_coord_get(void *priv_data, struct coord *c, int count)
169     {
170     struct map_rect_priv *mr=priv_data;
171     if(mr) {
172     *c = mr->c;
173     return 1;
174     }
175     else {
176     return 0;
177     }
178     }
179    
180     static void
181     csv_attr_rewind(void *priv_data)
182     {
183     // struct map_rect_priv *mr=priv_data;
184     //TODO implement if needed
185     }
186    
187     static int
188     csv_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
189     {
190     int i, bAttrFound = 0;
191     GList* attr_list;
192     struct map_rect_priv *mr=priv_data;
193     enum attr_type *at = mr->m->attr_types;
194    
195     for(i=0;i<mr->m->attr_cnt;++i) {
196     if(*at == attr_type) {
197     bAttrFound = 1;
198     break;
199     }
200     ++at;
201     }
202    
203     if(!bAttrFound) {
204     return 0;
205     }
206    
207     if(!mr || !mr->curr_item || !mr->curr_item->data ) {
208     return 0;
209     }
210    
211     attr_list = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->attr_list;
212    
213     while(attr_list) {
214     if(((struct attr*)attr_list->data)->type == attr_type) {
215     *attr = *(struct attr*)attr_list->data;
216     return 1;
217     }
218     attr_list = g_list_next(attr_list);
219     }
220     return 0;
221     }
222    
223     static int
224     csv_attr_set(void *priv_data, struct attr *attr, enum change_mode mode)
225     {
226     struct map_rect_priv* mr = (struct map_rect_priv*)priv_data;
227     struct map_priv* m = mr->m;
228     int i, bFound = 0;
229     struct attr *attr_new;
230     GList *attr_list, *curr_attr_list;
231     enum attr_type *at = m->attr_types;
232    
233     if(!mr || !mr->curr_item || !mr->curr_item->data ) {
234     return 0;
235     }
236    
237     //if attribute is not supported by this csv map return 0
238     for(i=0;i<m->attr_cnt;++i) {
239     if(*at==attr->type) {
240     bFound = 1;
241     break;
242     }
243     ++at;
244     }
245     if( ! bFound) {
246     return 0;
247     }
248     m->dirty = 1;
249     attr_new = attr_dup(attr);
250     attr_list = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->attr_list;
251     curr_attr_list = attr_list;
252    
253     while(attr_list) {
254     if(((struct attr*)attr_list->data)->type == attr->type) {
255     switch(mode) {
256     case change_mode_delete:
257     curr_attr_list = g_list_delete_link(curr_attr_list,attr_list->data);
258     return 1;
259     case change_mode_modify:
260     case change_mode_prepend:
261     case change_mode_append:
262     //replace existing attribute
263     if((struct attr*)attr_list->data) {
264     g_free((struct attr*)attr_list->data);
265     }
266     attr_list->data = attr_new;
267     m->dirty = 1;
268     save_map_csv(m);
269     return 1;
270     default:
271     g_free(attr_new);
272     return 0;
273     }
274     }
275     attr_list = g_list_next(attr_list);
276     }
277    
278     if( mode==change_mode_modify || mode==change_mode_prepend || mode==change_mode_append) {
279     //add new attribute
280     curr_attr_list = g_list_prepend(curr_attr_list, attr_new);
281     ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->attr_list = curr_attr_list;
282     m->dirty = 1;
283     save_map_csv(m);
284     return 1;
285     }
286     g_free(attr_new);
287     return 0;
288     }
289    
290     static struct item_methods methods_csv = {
291     csv_coord_rewind,
292     csv_coord_get,
293     csv_attr_rewind,
294     csv_attr_get,
295     NULL,
296     csv_attr_set,
297     csv_coord_set,
298     };
299    
300    
301     /*
302     * Sets coordinate of an existing item (either on the new list or an item with coord )
303     */
304     static int
305     csv_coord_set(void *priv_data, struct coord *c, int count, enum change_mode mode)
306     {
307     struct quadtree_item query_item, insert_item, *query_res;
308     struct coord_geo cg;
309     struct map_rect_priv* mr;
310     struct map_priv* m;
311     struct quadtree_item* qi;
312     GList* new_it;
313    
314     //for now we only support coord modification only
315     if( ! change_mode_modify) {
316     return 0;
317     }
318     //csv driver supports one coord per record only
319     if( count != 1) {
320     return 0;
321     }
322    
323     //get curr_item of given map_rect
324     mr = (struct map_rect_priv*)priv_data;
325     m = mr->m;
326    
327     if(!mr->curr_item || !mr->curr_item->data) {
328     return 0;
329     }
330    
331     qi = mr->curr_item->data;
332    
333     transform_to_geo(projection_mg, &c[0], &cg);
334    
335     //if it is on the new list remove from new list and add it to the tree with the coord
336     new_it = m->new_items;
337     while(new_it) {
338     if(new_it->data==qi) {
339     break;
340     }
341     new_it = g_list_next(new_it);
342     }
343     if(new_it) {
344     qi->longitude = cg.lng;
345     qi->latitude = cg.lat;
346     quadtree_add( m->tree_root, qi);
347     m->new_items = g_list_remove_link(m->new_items,new_it);
348     return 0;
349     }
350    
351     //else update quadtree item with the new coord
352     // remove item from the quadtree (to be implemented)
353     query_item.longitude = cg.lng;
354     query_item.latitude = cg.lat;
355     query_res = quadtree_find_item(m->tree_root, &query_item);
356     if(!query_res) {
357     return 0;
358     }
359     // add item to the tree with the new coord
360     insert_item = *query_res;
361     insert_item.longitude = cg.lng;
362     insert_item.latitude = cg.lat;
363     quadtree_delete_item(m->tree_root, query_res);
364     g_free(query_res);
365     quadtree_add( m->tree_root, &insert_item);
366     m->dirty = 1;
367     save_map_csv(m);
368     return 1;
369     }
370    
371     static struct map_rect_priv *
372     map_rect_new_csv(struct map_priv *map, struct map_selection *sel)
373     {
374     struct map_rect_priv *mr;
375     struct coord_geo lu;
376     struct coord_geo rl;
377     GList*res = NULL;
378    
379     dbg(1,"map_rect_new_csv\n");
380     mr=g_new0(struct map_rect_priv, 1);
381     mr->m=map;
382     mr->bStarted = 0;
383     mr->sel=sel;
384     if (map->flags & 1)
385     mr->item.id_hi=1;
386     else
387     mr->item.id_hi=0;
388     mr->item.id_lo=0;
389     mr->item.meth=&methods_csv;
390     mr->item.priv_data=mr;
391    
392     //convert selection to geo
393     if(sel) {
394     transform_to_geo(projection_mg, &sel->u.c_rect.lu, &lu);
395     transform_to_geo(projection_mg, &sel->u.c_rect.rl, &rl);
396     quadtree_find_rect_items(map->tree_root, lu.lng, rl.lng, rl.lat, lu.lat, &res);
397     }
398     mr->query_result = res;
399     mr->curr_item = res;
400     return mr;
401     }
402    
403    
404     static void
405     map_rect_destroy_csv(struct map_rect_priv *mr)
406     {
407     g_list_free(mr->query_result);
408     g_free(mr);
409     }
410    
411     static struct item *
412     map_rect_get_item_csv(struct map_rect_priv *mr)
413     {
414     if(mr->bStarted) {
415     if(mr->curr_item) {
416     mr->curr_item = g_list_next(mr->curr_item);
417     }
418     }
419     else {
420     mr->bStarted = 1;
421     }
422    
423     if(mr->curr_item) {
424     struct item* ret;
425     struct coord_geo cg;
426     ret = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->item;
427     ret->priv_data=mr;
428     if(mr->curr_item && mr->curr_item->data) {
429     cg.lng = ((struct quadtree_item*)(mr->curr_item->data))->longitude;
430     cg.lat = ((struct quadtree_item*)(mr->curr_item->data))->latitude;
431     transform_from_geo(projection_mg, &cg, &mr->c);
432     ret = ((struct quadtree_data*)(((struct quadtree_item*)(mr->curr_item->data))->data))->item;
433     return ret;
434     }
435     }
436     return NULL;
437     }
438    
439     static struct item *
440     map_rect_get_item_byid_csv(struct map_rect_priv *mr, int id_hi, int id_lo)
441     {
442     //currently id_hi is ignored
443     struct item *it = g_hash_table_lookup(mr->m->item_hash,&id_lo);
444     struct quadtree_item *qit = g_hash_table_lookup(mr->m->qitem_hash,&id_lo);
445     if(it && qit) {
446     mr->curr_item = g_list_prepend(NULL, qit);
447     }
448     else {
449     mr->curr_item = NULL;
450     }
451     return it;
452     }
453    
454     static int
455     csv_get_attr(struct map_priv *m, enum attr_type type, struct attr *attr)
456     {
457     return 0;
458     }
459    
460     static struct item *
461     csv_create_item(struct map_rect_priv *mr, enum item_type it_type)
462     {
463     struct map_priv* m;
464     struct quadtree_data* qd;
465     struct quadtree_item* qi;
466     struct item* curr_item;
467     int* pID;
468     if(mr && mr->m) {
469     m = mr->m;
470     }
471     else {
472     return NULL;
473     }
474    
475     if( m->item_type != it_type) {
476     return NULL;
477     }
478    
479     m->dirty = 1;
480     //add item to the map
481     curr_item = item_new("",zoom_max);
482     curr_item->type = m->item_type;
483     curr_item->priv_data = mr;
484    
485     curr_item->id_lo = m->next_item_idx;
486     if (m->flags & 1)
487     curr_item->id_hi=1;
488     else
489     curr_item->id_hi=0;
490     curr_item->meth=&methods_csv;
491    
492     qd = g_new0(struct quadtree_data,1);
493     qi = g_new0(struct quadtree_item,1);
494     qd->item = curr_item;
495     qd->attr_list = NULL;
496     qi->data = qd;
497     //we don`t have valid coord yet
498     qi->longitude = 0;
499     qi->latitude = 0;
500     //add the coord less item to the new list
501     //TODO remove unnecessary indirection
502     m->new_items = g_list_prepend(m->new_items, qi);
503     mr->curr_item = m->new_items;
504     //don't add to the quadtree yet, wait until we have a valid coord
505     pID = g_new(int,1);
506     *pID = m->next_item_idx;
507     g_hash_table_insert(m->item_hash, pID,curr_item);
508     g_hash_table_insert(m->qitem_hash, pID,qi);
509     ++m->next_item_idx;
510     return curr_item;
511     }
512    
513     static struct map_methods map_methods_csv = {
514     projection_mg,
515     "iso8859-1",
516     map_destroy_csv,
517     map_rect_new_csv,
518     map_rect_destroy_csv,
519     map_rect_get_item_csv,
520     map_rect_get_item_byid_csv,
521     NULL,
522     NULL,
523     NULL,
524     csv_create_item,
525     csv_get_attr,
526     };
527    
528 zoff99 40 struct map_priv *
529 zoff99 2 map_new_csv(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
530     {
531     struct map_priv *m = NULL;
532     struct attr *item_type;
533     struct attr *attr_types;
534     struct attr *item_type_attr;
535     struct attr *data;
536     struct attr *flags;
537     int bLonFound = 0;
538     int bLatFound = 0;
539     int attr_cnt = 0;
540     enum attr_type* attr_type_list = NULL;
541     struct quadtree_node* tree_root = quadtree_node_new(NULL,-90,90,-90,90);
542     m = g_new0(struct map_priv, 1);
543     m->id = ++map_id;
544     m->qitem_hash = g_hash_table_new(g_int_hash, g_int_equal);
545 zoff99 31 m->item_hash = g_hash_table_new_full(g_int_hash, g_int_equal,g_free_func,g_free_func);
546 zoff99 2
547     item_type = attr_search(attrs, NULL, attr_item_type);
548     attr_types = attr_search(attrs, NULL, attr_attr_types);
549     if(attr_types) {
550     enum attr_type* at = attr_types->u.attr_types;
551     while(*at != attr_none) {
552     attr_type_list = g_realloc(attr_type_list,sizeof(enum attr_type)*(attr_cnt+1));
553     attr_type_list[attr_cnt] = *at;
554     if(*at==attr_position_latitude) {
555     bLatFound = 1;
556     }
557     else if(*at==attr_position_longitude) {
558     bLonFound = 1;
559     }
560     ++attr_cnt;
561     ++at;
562     }
563     m->attr_cnt = attr_cnt;
564     m->attr_types = attr_type_list;
565     }
566     else {
567     return NULL;
568     }
569    
570     if(bLonFound==0 || bLatFound==0) {
571     return NULL;
572     }
573    
574     item_type_attr=attr_search(attrs, NULL, attr_item_type);
575    
576     if( !item_type_attr || item_type_attr->u.item_type==type_none) {
577     return NULL;
578     }
579    
580     m->item_type = item_type_attr->u.item_type;
581    
582     data=attr_search(attrs, NULL, attr_data);
583    
584     if(data) {
585     //load csv file into quadtree structure
586     //if column number is wrong skip
587     FILE*fp;
588     if((fp=fopen(data->u.str,"rt"))) {
589     const int max_line_len = 256;
590     char *line=g_alloca(sizeof(char)*max_line_len);
591     while(!feof(fp)) {
592     if(fgets(line,max_line_len,fp)) {
593     char*line2;
594     char* delim = ",";
595     int col_cnt=0;
596     char*tok;
597    
598     if(line[strlen(line)-1]=='\n' || line[strlen(line)-1]=='\r') {
599     line[strlen(line)-1] = '\0';
600     }
601     line2 = g_strdup(line);
602     while((tok=strtok( (col_cnt==0)?line:NULL , delim))) {
603     ++col_cnt;
604     }
605    
606     if(col_cnt==attr_cnt) {
607     int cnt = 0; //idx of current attr
608     char*tok;
609     GList* attr_list = NULL;
610     int bAddSum = 1;
611     double longitude = 0.0, latitude=0.0;
612     struct item *curr_item = item_new("",zoom_max);//does not use parameters
613     curr_item->type = item_type_attr->u.item_type;
614     curr_item->id_lo = m->next_item_idx;
615     if (m->flags & 1)
616     curr_item->id_hi=1;
617     else
618     curr_item->id_hi=0;
619     curr_item->meth=&methods_csv;
620    
621    
622     while((tok=strtok( (cnt==0)?line2:NULL , delim))) {
623     struct attr*curr_attr = g_new0(struct attr,1);
624     int bAdd = 1;
625     curr_attr->type = attr_types->u.attr_types[cnt];
626     if(ATTR_IS_STRING(attr_types->u.attr_types[cnt])) {
627     curr_attr->u.str = g_strdup(tok);
628     }
629     else if(ATTR_IS_INT(attr_types->u.attr_types[cnt])) {
630     curr_attr->u.num = atoi(tok);
631     }
632     else if(ATTR_IS_DOUBLE(attr_types->u.attr_types[cnt])) {
633     double *d = g_new(double,1);
634     *d = atof(tok);
635     curr_attr->u.numd = d;
636     if(attr_types->u.attr_types[cnt] == attr_position_longitude) {
637     longitude = *d;
638     }
639     if(attr_types->u.attr_types[cnt] == attr_position_latitude) {
640     latitude = *d;
641     }
642     }
643     else {
644     //unknown attribute
645     bAddSum = bAdd = 0;
646     g_free(curr_attr);
647     }
648    
649     if(bAdd) {
650     attr_list = g_list_prepend(attr_list, curr_attr);
651     }
652     ++cnt;
653     }
654     if(bAddSum && (longitude!=0.0 || latitude!=0.0)) {
655     struct quadtree_data* qd = g_new0(struct quadtree_data,1);
656     struct quadtree_item* qi =g_new(struct quadtree_item,1);
657     int* pID = g_new(int,1);
658     qd->item = curr_item;
659     qd->attr_list = attr_list;
660     qi->data = qd;
661     qi->longitude = longitude;
662     qi->latitude = latitude;
663     quadtree_add(tree_root, qi);
664     *pID = m->next_item_idx;
665     g_hash_table_insert(m->item_hash, pID,curr_item);
666     g_hash_table_insert(m->qitem_hash, pID,qi);
667     ++m->next_item_idx;
668     }
669     else {
670     g_free(curr_item);
671     }
672    
673     }
674     else {
675     //printf("ERROR: Non-matching attr count and column count: %d %d SKIPPING line: %s\n",col_cnt, attr_cnt,line);
676     }
677     g_free(line2);
678     }
679     }
680     fclose(fp);
681     m->filename = g_strdup(data->u.str);
682     }
683     else {
684     return NULL;
685     }
686     }
687    
688     *meth = map_methods_csv;
689     m->tree_root = tree_root;
690     flags=attr_search(attrs, NULL, attr_flags);
691     if (flags)
692     m->flags=flags->u.num;
693     return m;
694     }
695    
696 zoff99 40 #ifdef PLUGSSS
697 zoff99 2 void
698     plugin_init(void)
699     {
700     dbg(1,"csv: plugin_init\n");
701     plugin_register_map_type("csv", map_new_csv);
702     }
703 zoff99 40 #endif
704 zoff99 2

   
Visit the ZANavi Wiki