diff options
Diffstat (limited to 'map/textfile/textfile.c')
-rw-r--r-- | map/textfile/textfile.c | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/map/textfile/textfile.c b/map/textfile/textfile.c new file mode 100644 index 00000000..2bdf07d9 --- /dev/null +++ b/map/textfile/textfile.c @@ -0,0 +1,405 @@ +/** + * Navit, a modular navigation system. + * Copyright (C) 2005-2008 Navit Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "config.h" +#include "debug.h" +#include "plugin.h" +#include "projection.h" +#include "item.h" +#include "map.h" +#include "maptype.h" +#include "attr.h" +#include "transform.h" +#include "file.h" + +#include "textfile.h" + +static int map_id; + +static int +get_tag(char *line, char *name, int *pos, char *ret, char *name_ret) +{ + int len=0,quoted; + char *p,*e,*n; + + dbg(1,"get_tag %s from %s\n", name, line); + if (name) + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=strchr(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (name == NULL || (e-n == len && !strncmp(n, name, len))) { + if (name_ret) { + len=e-n; + strncpy(name_ret, n, len); + name_ret[len]='\0'; + } + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(ret, e, len); + ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} + +static void +get_line(struct map_rect_priv *mr) +{ + if(mr->f) { + if (!mr->m->is_pipe) + mr->pos=ftell(mr->f); + else + mr->pos+=mr->lastlen; + fgets(mr->line, SIZE, mr->f); + mr->lastlen=strlen(mr->line)+1; + if (strlen(mr->line) >= SIZE-1) + printf("line too long\n"); + } +} + +static void +map_destroy_textfile(struct map_priv *m) +{ + dbg(1,"map_destroy_textfile\n"); + g_free(m); +} + +static void +textfile_coord_rewind(void *priv_data) +{ +} + +static int +parse_line(struct map_rect_priv *mr, int attr) +{ + int pos; + + pos=coord_parse(mr->line, projection_mg, &mr->c); + if (pos < strlen(mr->line) && attr) { + strcpy(mr->attrs, mr->line+pos); + } + return pos; +} + +static int +textfile_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + int ret=0; + dbg(1,"textfile_coord_get %d\n",count); + while (count--) { + if (mr->f && !feof(mr->f) && (!mr->item.id_hi || !mr->eoc) && parse_line(mr, mr->item.id_hi)) { + *c=mr->c; + dbg(1,"c=0x%x,0x%x\n", c->x, c->y); + c++; + ret++; + get_line(mr); + if (mr->item.id_hi) + mr->eoc=1; + } else { + mr->more=0; + break; + } + } + return ret; +} + +static void +textfile_attr_rewind(void *priv_data) +{ +} + +static void +textfile_encode_attr(char *attr_val, enum attr_type attr_type, struct attr *attr) +{ + if (attr_type >= attr_type_int_begin && attr_type <= attr_type_int_end) + attr->u.num=atoi(attr_val); + else + attr->u.str=attr_val; +} + +static int +textfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + char *str=NULL; + dbg(1,"textfile_attr_get mr=%p attrs='%s' ", mr, mr->attrs); + if (attr_type != mr->attr_last) { + dbg(1,"reset attr_pos\n"); + mr->attr_pos=0; + mr->attr_last=attr_type; + } + if (attr_type == attr_any) { + dbg(1,"attr_any"); + if (get_tag(mr->attrs,NULL,&mr->attr_pos,mr->attr, mr->attr_name)) { + attr_type=attr_from_name(mr->attr_name); + dbg(1,"found attr '%s' 0x%x\n", mr->attr_name, attr_type); + attr->type=attr_type; + textfile_encode_attr(mr->attr, attr_type, attr); + return 1; + } + } else { + str=attr_to_name(attr_type); + dbg(1,"attr='%s' ",str); + if (get_tag(mr->attrs,str,&mr->attr_pos,mr->attr, NULL)) { + textfile_encode_attr(mr->attr, attr_type, attr); + dbg(1,"found\n"); + return 1; + } + } + dbg(1,"not found\n"); + return 0; +} + +static struct item_methods methods_textfile = { + textfile_coord_rewind, + textfile_coord_get, + textfile_attr_rewind, + textfile_attr_get, +}; + +static struct map_rect_priv * +map_rect_new_textfile(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + + dbg(1,"map_rect_new_textfile\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + mr->sel=sel; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.meth=&methods_textfile; + mr->item.priv_data=mr; + if (map->is_pipe) { + char *oargs,*args=g_strdup(map->filename),*sep=" "; + enum layer_type lay; + g_free(mr->args); + while (sel) { + oargs=args; + 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); + g_free(oargs); + for (lay=layer_town ; lay < layer_end ; lay++) { + oargs=args; + args=g_strdup_printf("%s%s%d", oargs, sep, sel->order); + g_free(oargs); + sep=","; + } + sel=sel->next; + } + dbg(1,"popen args %s\n", args); + mr->args=args; + mr->f=popen(mr->args, "r"); + mr->pos=0; + mr->lastlen=0; + } else { + mr->f=fopen(map->filename, "r"); + } + if(!mr->f) { + printf("map_rect_new_textfile unable to open textfile %s\n",map->filename); + } + get_line(mr); + return mr; +} + + +static void +map_rect_destroy_textfile(struct map_rect_priv *mr) +{ + if (mr->f) { + if (mr->m->is_pipe) + pclose(mr->f); + else + fclose(mr->f); + } + g_free(mr); +} + +static struct item * +map_rect_get_item_textfile(struct map_rect_priv *mr) +{ + char *p,type[SIZE]; + dbg(1,"map_rect_get_item_textfile id_hi=%d line=%s", mr->item.id_hi, mr->line); + if (!mr->f) { + return NULL; + } + while (mr->more) { + struct coord c; + textfile_coord_get(mr, &c, 1); + } + for(;;) { + if (feof(mr->f)) { + dbg(1,"map_rect_get_item_textfile: eof\n"); + if (mr->item.id_hi) { + return NULL; + } + mr->item.id_hi++; + if (mr->m->is_pipe) { + pclose(mr->f); + mr->f=popen(mr->args, "r"); + mr->pos=0; + mr->lastlen=0; + } else + fseek(mr->f, 0, SEEK_SET); + get_line(mr); + } + if ((p=strchr(mr->line,'\n'))) + *p='\0'; + if (mr->item.id_hi) { + mr->attrs[0]='\0'; + if (!parse_line(mr, 1)) { + get_line(mr); + continue; + } + dbg(1,"map_rect_get_item_textfile: point found\n"); + mr->eoc=0; + mr->item.id_lo=mr->pos; + } else { + if (parse_line(mr, 1)) { + get_line(mr); + continue; + } + dbg(1,"map_rect_get_item_textfile: line found\n"); + if (! mr->line[0]) { + get_line(mr); + continue; + } + mr->item.id_lo=mr->pos; + strcpy(mr->attrs, mr->line); + get_line(mr); + dbg(1,"mr=%p attrs=%s\n", mr, mr->attrs); + } + dbg(1,"get_attrs %s\n", mr->attrs); + if (get_tag(mr->attrs,"type",NULL,type,NULL)) { + dbg(1,"type='%s'\n", type); + mr->item.type=item_from_name(type); + if (mr->item.type == type_none) + printf("Warning: type '%s' unknown\n", type); + } else { + get_line(mr); + continue; + } + mr->attr_last=attr_none; + mr->more=1; + dbg(1,"return attr='%s'\n", mr->attrs); + return &mr->item; + } +} + +static struct item * +map_rect_get_item_byid_textfile(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + if (mr->m->is_pipe) { + pclose(mr->f); + mr->f=popen(mr->args, "r"); + mr->pos=0; + mr->lastlen=0; + } else + fseek(mr->f, id_lo, SEEK_SET); + get_line(mr); + mr->item.id_hi=id_hi; + return map_rect_get_item_textfile(mr); +} + +static struct map_methods map_methods_textfile = { + projection_mg, + "iso8859-1", + map_destroy_textfile, + map_rect_new_textfile, + map_rect_destroy_textfile, + map_rect_get_item_textfile, + map_rect_get_item_byid_textfile, +}; + +static struct map_priv * +map_new_textfile(struct map_methods *meth, struct attr **attrs) +{ + struct map_priv *m; + struct attr *data=attr_search(attrs, NULL, attr_data); + struct attr *charset=attr_search(attrs, NULL, attr_charset); + struct file_wordexp *wexp; + int len,is_pipe=0; + char *wdata; + char **wexp_data; + if (! data) + return NULL; + dbg(1,"map_new_textfile %s\n", data->u.str); + wdata=g_strdup(data->u.str); + len=strlen(wdata); + if (len && wdata[len-1] == '|') { + wdata[len-1]='\0'; + is_pipe=1; + } + wexp=file_wordexp_new(wdata); + wexp_data=file_wordexp_get_array(wexp); + *meth=map_methods_textfile; + + m=g_new0(struct map_priv, 1); + m->id=++map_id; + m->filename=g_strdup(wexp_data[0]); + m->is_pipe=is_pipe; + dbg(1,"map_new_textfile %s %s\n", m->filename, wdata); + if (charset) { + m->charset=g_strdup(charset->u.str); + meth->charset=m->charset; + } + file_wordexp_destroy(wexp); + return m; +} + +void +plugin_init(void) +{ + dbg(1,"textfile: plugin_init\n"); + plugin_register_map_type("textfile", map_new_textfile); +} + |