diff options
author | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2009-07-30 20:34:23 +0000 |
---|---|---|
committer | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2009-07-30 20:34:23 +0000 |
commit | d72782347c2ba802cd030feeb23f7eacc4ae8a23 (patch) | |
tree | a729476323d0d551c2031b3a666193923ceb08a4 /attr.c | |
parent | c297ef7f5928b0407ab67b9a76ccf166d0a1d3e0 (diff) | |
parent | 3b8435d744c504a88493f272068453023585837e (diff) | |
download | navit-svn-wince.tar.gz |
Updated wince branch to current versionwince
git-svn-id: http://svn.code.sf.net/p/navit/code/branches/wince/navit@2430 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'attr.c')
-rw-r--r-- | attr.c | 546 |
1 files changed, 546 insertions, 0 deletions
@@ -0,0 +1,546 @@ +/** + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <glib.h> +#include "debug.h" +#include "item.h" +#include "coord.h" +#include "transform.h" +#include "color.h" +#include "attr.h" +#include "map.h" +#include "config.h" +#include "endianess.h" + +struct attr_name { + enum attr_type attr; + char *name; +}; + + +static struct attr_name attr_names[]={ +#define ATTR2(x,y) ATTR(y) +#define ATTR(x) { attr_##x, #x }, +#include "attr_def.h" +#undef ATTR2 +#undef ATTR +}; + +enum attr_type +attr_from_name(const char *name) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (! strcmp(attr_names[i].name, name)) + return attr_names[i].attr; + } + return attr_none; +} + +char * +attr_to_name(enum attr_type attr) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (attr_names[i].attr == attr) + return attr_names[i].name; + } + return NULL; +} + +struct attr * +attr_new_from_text(const char *name, const char *value) +{ + enum attr_type attr; + struct attr *ret; + struct coord_geo *g; + struct coord c; + char *pos,*type_str,*str,*tok; + int min,max,count; + + ret=g_new0(struct attr, 1); + dbg(1,"enter name='%s' value='%s'\n", name, value); + attr=attr_from_name(name); + ret->type=attr; + switch (attr) { + case attr_item_type: + ret->u.item_type=item_from_name(value); + break; + case attr_item_types: + count=0; + type_str=g_strdup(value); + str=type_str; + while ((tok=strtok(str, ","))) { + ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type)); + ret->u.item_types[count++]=item_from_name(tok); + ret->u.item_types[count]=type_none; + str=NULL; + } + g_free(type_str); + break; + case attr_dash: + count=0; + type_str=g_strdup(value); + str=type_str; + while ((tok=strtok(str, ","))) { + ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int)); + ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0); + ret->u.dash[count]=0; + str=NULL; + } + g_free(type_str); + break; + case attr_order: + case attr_sequence_range: + case attr_angle_range: + case attr_speed_range: + pos=strchr(value, '-'); + min=0; + max=32767; + if (! pos) { + sscanf(value,"%d",&min); + max=min; + } else if (pos == value) + sscanf(value,"-%d",&max); + else + sscanf(value,"%d-%d",&min, &max); + ret->u.range.min=min; + ret->u.range.max=max; + break; + default: + if (attr >= attr_type_string_begin && attr <= attr_type_string_end) { + ret->u.str=(char *)value; + break; + } + if (attr >= attr_type_int_begin && attr <= attr_type_int_end) { + if (value[0] == '0' && value[1] == 'x') + ret->u.num=strtoul(value, NULL, 0); + else + ret->u.num=strtol(value, NULL, 0); + + if ((attr >= attr_type_rel_abs_begin) && (attr < attr_type_boolean_begin)) { + /* Absolute values are from -0x40000000 - 0x40000000, with 0x0 being 0 (who would have thought that?) + Relative values are from 0x40000001 - 0x80000000, with 0x60000000 being 0 */ + if (strchr(value, '%')) { + if ((ret->u.num > 0x20000000) || (ret->u.num < -0x1FFFFFFF)) { + dbg(0, "Relative possibly-relative attribute with invalid value %i\n", ret->u.num); + } + + ret->u.num += 0x60000000; + } else { + if ((ret->u.num > 0x40000000) || (ret->u.num < -0x40000000)) { + dbg(0, "Non-relative possibly-relative attribute with invalid value %i\n", ret->u.num); + } + } + } else if (attr >= attr_type_boolean_begin) { // also check for yes and no + if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false")) + ret->u.num=1; + else + ret->u.num=0; + } + break; + } + if (attr >= attr_type_color_begin && attr <= attr_type_color_end) { + struct color *color=g_new0(struct color, 1); + int r,g,b,a; + ret->u.color=color; + if(strlen(value)==7){ + sscanf(value,"#%02x%02x%02x", &r, &g, &b); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + color->a = (65535); + } else if(strlen(value)==9){ + sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + color->a = (a << 8) | a; + } else { + dbg(0,"color %s has unknown format\n",value); + } + break; + } + if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) { + g=g_new(struct coord_geo, 1); + ret->u.coord_geo=g; + coord_parse(value, projection_mg, &c); + transform_to_geo(projection_mg, &c, g); + break; + } + dbg(1,"default\n"); + g_free(ret); + ret=NULL; + } + return ret; +} + +char * +attr_to_text(struct attr *attr, struct map *map, int pretty) +{ + char *ret; + enum attr_type type=attr->type; + + if (type >= attr_type_item_begin && type <= attr_type_item_end) { + struct item *item=attr->u.item; + struct attr type, data; + if (! item) + return g_strdup("(nil)"); + if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL)) + type.u.str=""; + if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL)) + data.u.str=""; + return g_strdup_printf("type=0x%x id=0x%x,0x%x map=%p (%s:%s)", item->type, item->id_hi, item->id_lo, item->map, type.u.str, data.u.str); + } + if (type >= attr_type_string_begin && type <= attr_type_string_end) { + if (map) { + char *mstr; + if (attr->u.str) { + mstr=map_convert_string(map, attr->u.str); + ret=g_strdup(mstr); + map_convert_free(mstr); + } else + ret=g_strdup("(null)"); + + } else + ret=g_strdup(attr->u.str); + return ret; + } + if (type == attr_flags) + return g_strdup_printf("0x%x", attr->u.num); + if (type >= attr_type_int_begin && type <= attr_type_int_end) + return g_strdup_printf("%d", attr->u.num); + if (type >= attr_type_int64_begin && type <= attr_type_int64_end) + return g_strdup_printf("%Ld", *attr->u.num64); + if (type >= attr_type_double_begin && type <= attr_type_double_end) + return g_strdup_printf("%f", *attr->u.numd); + if (type >= attr_type_object_begin && type <= attr_type_object_end) + return g_strdup_printf("(object[%s])", attr_to_name(type)); + return g_strdup_printf("(no text[%s])", attr_to_name(type)); +} + +struct attr * +attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) +{ + dbg(1, "enter attrs=%p\n", attrs); + while (*attrs) { + dbg(1,"*attrs=%p\n", *attrs); + if ((*attrs)->type == attr) { + return *attrs; + } + attrs++; + } + return NULL; +} + +int +attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter) +{ + while (attrs && *attrs) { + if ((*attrs)->type == type) { + *attr=**attrs; + return 1; + } + attrs++; + } + while (def_attrs && *def_attrs) { + if ((*def_attrs)->type == type) { + *attr=**def_attrs; + return 1; + } + def_attrs++; + } + return 0; +} + +struct attr ** +attr_generic_set_attr(struct attr **attrs, struct attr *attr) +{ + struct attr **curr=attrs; + int i,count=0; + while (curr && *curr) { + if ((*curr)->type == attr->type) { + attr_free(*curr); + *curr=attr_dup(attr); + return attrs; + } + curr++; + count++; + } + curr=g_new0(struct attr *, count+2); + for (i = 0 ; i < count ; i++) + curr[i]=attrs[i]; + curr[count]=attr_dup(attr); + curr[count+1]=NULL; + g_free(attrs); + return curr; +} + +struct attr ** +attr_generic_add_attr(struct attr **attrs, struct attr *attr) +{ + struct attr **curr=attrs; + int i,count=0; + while (curr && *curr) { + curr++; + count++; + } + curr=g_new0(struct attr *, count+2); + for (i = 0 ; i < count ; i++) + curr[i]=attrs[i]; + curr[count]=attr_dup(attr); + curr[count+1]=NULL; + g_free(attrs); + return curr; +} + +struct attr ** +attr_generic_remove_attr(struct attr **attrs, struct attr *attr) +{ + struct attr **curr=attrs; + int i,j,count=0,found=0; + while (curr && *curr) { + if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data) + found=1; + curr++; + count++; + } + if (!found == -1) + return attrs; + curr=g_new0(struct attr *, count); + j=0; + for (i = 0 ; i < count ; i++) { + if ((*curr)->type != attr->type || (*curr)->u.data != attr->u.data) + curr[j++]=attrs[i]; + else + attr_free(attrs[i]); + } + curr[j]=NULL; + g_free(attrs); + return curr; +} + +enum attr_type +attr_type_begin(enum attr_type type) +{ + if (type < attr_type_item_begin) + return attr_none; + if (type < attr_type_int_begin) + return attr_type_item_begin; + if (type < attr_type_string_begin) + return attr_type_int_begin; + if (type < attr_type_special_begin) + return attr_type_string_begin; + if (type < attr_type_double_begin) + return attr_type_special_begin; + if (type < attr_type_coord_geo_begin) + return attr_type_double_begin; + if (type < attr_type_color_begin) + return attr_type_coord_geo_begin; + if (type < attr_type_object_begin) + return attr_type_color_begin; + if (type < attr_type_coord_begin) + return attr_type_object_begin; + if (type < attr_type_pcoord_begin) + return attr_type_coord_begin; + if (type < attr_type_callback_begin) + return attr_type_pcoord_begin; + if (type < attr_type_int64_begin) + return attr_type_callback_begin; + if (type <= attr_type_int64_end) + return attr_type_int64_begin; + return attr_none; +} + +int +attr_data_size(struct attr *attr) +{ + if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) + return strlen(attr->u.str)+1; + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + return sizeof(attr->u.num); + if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) + return sizeof(*attr->u.coord_geo); + if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) + return sizeof(*attr->u.color); + if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) + return sizeof(void *); + if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end) + return sizeof(*attr->u.num64); + if (attr->type == attr_order) + return sizeof(attr->u.range); + if (attr->type == attr_item_types) { + int i=0; + while (attr->u.item_types[i++] != type_none); + return i*sizeof(enum item_type); + } + dbg(0,"size for %s unknown\n", attr_to_name(attr->type)); + return 0; +} + +void * +attr_data_get(struct attr *attr) +{ + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + return &attr->u.num; + if (attr->type == attr_order) + return &attr->u.range; + return attr->u.data; +} + +void +attr_data_set(struct attr *attr, void *data) +{ + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + attr->u.num=*((int *)data); + else + attr->u.data=data; +} + +void +attr_data_set_le(struct attr * attr, void * data) +{ + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + attr->u.num=le32_to_cpu(*((int *)data)); + else if (attr->type == attr_order) { + attr->u.num=le32_to_cpu(*((int *)data)); + attr->u.range.min=le16_to_cpu(attr->u.range.min); + attr->u.range.max=le16_to_cpu(attr->u.range.max); + } + else +/* Fixme: Handle long long */ + attr->u.data=data; + +} + +void +attr_free(struct attr *attr) +{ + if (!attr) + return; + if (attr->type == attr_position_coord_geo) + g_free(attr->u.coord_geo); + if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) + g_free(attr->u.color); + g_free(attr); +} + +struct attr * +attr_dup(struct attr *attr) +{ + int size; + struct attr *ret=g_new0(struct attr, 1); + ret->type=attr->type; + if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) + ret->u.num=attr->u.num; + else if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) + ret->u.data=attr->u.data; + else { + size=attr_data_size(attr); + if (size) { + ret->u.data=g_malloc(size); + memcpy(ret->u.data, attr->u.data, size); + } + } + return ret; +} + +void +attr_list_free(struct attr **attrs) +{ + int count=0; + while (attrs && attrs[count]) { + attr_free(attrs[count++]); + } + g_free(attrs); +} + +struct attr ** +attr_list_dup(struct attr **attrs) +{ + struct attr **ret=attrs; + int i,count=0; + + while (attrs[count]) + count++; + ret=g_new0(struct attr *, count+1); + for (i = 0 ; i < count ; i++) + ret[i]=attr_dup(attrs[i]); + return ret; +} + + +int +attr_from_line(char *line, char *name, int *pos, char *val_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(val_ret, e, len); + val_ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} |