2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
27 #include "transform.h"
32 #include "endianess.h"
40 static struct attr_name attr_names[]={
41 #define ATTR2(x,y) ATTR(y)
42 #define ATTR(x) { attr_##x, #x },
49 attr_from_name(const char *name)
53 for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
54 if (! strcmp(attr_names[i].name, name))
55 return attr_names[i].attr;
61 static int attr_match(enum attr_type search, enum attr_type found);
66 attr_to_name(enum attr_type attr)
70 for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
71 if (attr_names[i].attr == attr)
72 return attr_names[i].name;
78 attr_new_from_text(const char *name, const char *value)
84 char *pos,*type_str,*str,*tok;
87 ret=g_new0(struct attr, 1);
88 dbg(1,"enter name='%s' value='%s'\n", name, value);
89 attr=attr_from_name(name);
93 ret->u.item_type=item_from_name(value);
97 type_str=g_strdup(value);
99 while ((tok=strtok(str, ","))) {
100 ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type));
101 ret->u.item_types[count++]=item_from_name(tok);
102 ret->u.item_types[count]=type_none;
107 case attr_attr_types:
109 type_str=g_strdup(value);
111 while ((tok=strtok(str, ","))) {
112 ret->u.attr_types=g_realloc(ret->u.attr_types, (count+2)*sizeof(enum attr_type));
113 ret->u.attr_types[count++]=attr_from_name(tok);
114 ret->u.attr_types[count]=attr_none;
121 type_str=g_strdup(value);
123 while ((tok=strtok(str, ","))) {
124 ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int));
125 ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0);
126 ret->u.dash[count]=0;
132 case attr_sequence_range:
133 case attr_angle_range:
134 case attr_speed_range:
135 pos=strchr(value, '-');
139 sscanf(value,"%d",&min);
141 } else if (pos == value)
142 sscanf(value,"-%d",&max);
144 sscanf(value,"%d-%d",&min, &max);
145 ret->u.range.min=min;
146 ret->u.range.max=max;
149 if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
150 ret->u.str=g_strdup(value);
153 if (attr >= attr_type_int_begin && attr <= attr_type_int_end) {
154 if (value[0] == '0' && value[1] == 'x')
155 ret->u.num=strtoul(value, NULL, 0);
157 ret->u.num=strtol(value, NULL, 0);
159 if ((attr >= attr_type_rel_abs_begin) && (attr < attr_type_boolean_begin)) {
160 /* Absolute values are from -0x40000000 - 0x40000000, with 0x0 being 0 (who would have thought that?)
161 Relative values are from 0x40000001 - 0x80000000, with 0x60000000 being 0 */
162 if (strchr(value, '%')) {
163 if ((ret->u.num > 0x20000000) || (ret->u.num < -0x1FFFFFFF)) {
164 dbg(0, "Relative possibly-relative attribute with invalid value %i\n", ret->u.num);
167 ret->u.num += 0x60000000;
169 if ((ret->u.num > 0x40000000) || (ret->u.num < -0x40000000)) {
170 dbg(0, "Non-relative possibly-relative attribute with invalid value %i\n", ret->u.num);
173 } else if (attr >= attr_type_boolean_begin) { // also check for yes and no
174 if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))
181 if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
182 struct color *color=g_new0(struct color, 1);
185 if(strlen(value)==7){
186 sscanf(value,"#%02x%02x%02x", &r, &g, &b);
187 color->r = (r << 8) | r;
188 color->g = (g << 8) | g;
189 color->b = (b << 8) | b;
191 } else if(strlen(value)==9){
192 sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a);
193 color->r = (r << 8) | r;
194 color->g = (g << 8) | g;
195 color->b = (b << 8) | b;
196 color->a = (a << 8) | a;
198 dbg(0,"color %s has unknown format\n",value);
202 if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) {
203 g=g_new(struct coord_geo, 1);
205 coord_parse(value, projection_mg, &c);
206 transform_to_geo(projection_mg, &c, g);
217 attr_to_text(struct attr *attr, struct map *map, int pretty)
220 enum attr_type type=attr->type;
222 if (type >= attr_type_item_begin && type <= attr_type_item_end) {
223 struct item *item=attr->u.item;
224 struct attr type, data;
226 return g_strdup("(nil)");
227 if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL))
229 if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL))
231 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);
233 if (type >= attr_type_string_begin && type <= attr_type_string_end) {
237 mstr=map_convert_string(map, attr->u.str);
239 map_convert_free(mstr);
241 ret=g_strdup("(null)");
244 ret=g_strdup(attr->u.str);
247 if (type == attr_flags)
248 return g_strdup_printf("0x%x", attr->u.num);
249 if (type >= attr_type_int_begin && type <= attr_type_int_end)
250 return g_strdup_printf("%d", attr->u.num);
251 if (type >= attr_type_int64_begin && type <= attr_type_int64_end)
252 return g_strdup_printf("%Ld", *attr->u.num64);
253 if (type >= attr_type_double_begin && type <= attr_type_double_end)
254 return g_strdup_printf("%f", *attr->u.numd);
255 if (type >= attr_type_object_begin && type <= attr_type_object_end)
256 return g_strdup_printf("(object[%s])", attr_to_name(type));
257 if (type >= attr_type_color_begin && type <= attr_type_color_end) {
258 if (attr->u.color->a != 65535)
259 return g_strdup_printf("#%02x%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8, attr->u.color->a>>8);
261 return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8);
263 if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end)
264 return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat);
265 if (type == attr_zipfile_ref_block) {
266 int *data=attr->u.data;
267 return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]);
269 return g_strdup_printf("(no text[%s])", attr_to_name(type));
273 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
275 dbg(1, "enter attrs=%p\n", attrs);
277 dbg(1,"*attrs=%p\n", *attrs);
278 if ((*attrs)->type == attr) {
287 attr_match(enum attr_type search, enum attr_type found)
300 return search == found;
305 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
307 while (attrs && *attrs) {
308 if (attr_match(type,(*attrs)->type)) {
312 if (*((void **)iter) < (void *)attrs) {
313 *((void **)iter)=(void *)attrs;
319 if (type == attr_any || type == attr_any_xml)
321 while (def_attrs && *def_attrs) {
322 if ((*def_attrs)->type == type) {
332 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
334 struct attr **curr=attrs;
336 while (curr && *curr) {
337 if ((*curr)->type == attr->type) {
339 *curr=attr_dup(attr);
345 curr=g_new0(struct attr *, count+2);
346 for (i = 0 ; i < count ; i++)
348 curr[count]=attr_dup(attr);
355 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
357 struct attr **curr=attrs;
359 while (curr && *curr) {
363 curr=g_new0(struct attr *, count+2);
364 for (i = 0 ; i < count ; i++)
366 curr[count]=attr_dup(attr);
373 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
375 struct attr **curr=attrs;
376 int i,j,count=0,found=0;
377 while (curr && *curr) {
378 if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data)
385 curr=g_new0(struct attr *, count);
387 for (i = 0 ; i < count ; i++) {
388 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
399 attr_type_begin(enum attr_type type)
401 if (type < attr_type_item_begin)
403 if (type < attr_type_int_begin)
404 return attr_type_item_begin;
405 if (type < attr_type_string_begin)
406 return attr_type_int_begin;
407 if (type < attr_type_special_begin)
408 return attr_type_string_begin;
409 if (type < attr_type_double_begin)
410 return attr_type_special_begin;
411 if (type < attr_type_coord_geo_begin)
412 return attr_type_double_begin;
413 if (type < attr_type_color_begin)
414 return attr_type_coord_geo_begin;
415 if (type < attr_type_object_begin)
416 return attr_type_color_begin;
417 if (type < attr_type_coord_begin)
418 return attr_type_object_begin;
419 if (type < attr_type_pcoord_begin)
420 return attr_type_coord_begin;
421 if (type < attr_type_callback_begin)
422 return attr_type_pcoord_begin;
423 if (type < attr_type_int64_begin)
424 return attr_type_callback_begin;
425 if (type <= attr_type_int64_end)
426 return attr_type_int64_begin;
431 attr_data_size(struct attr *attr)
433 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end)
434 return strlen(attr->u.str)+1;
435 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
436 return sizeof(attr->u.num);
437 if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end)
438 return sizeof(*attr->u.coord_geo);
439 if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end)
440 return sizeof(*attr->u.color);
441 if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end)
442 return sizeof(void *);
443 if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end)
444 return sizeof(*attr->u.num64);
445 if (attr->type == attr_order)
446 return sizeof(attr->u.range);
447 if (attr->type == attr_item_types) {
449 while (attr->u.item_types[i++] != type_none);
450 return i*sizeof(enum item_type);
452 if (attr->type == attr_attr_types) {
454 while (attr->u.attr_types[i++] != attr_none);
455 return i*sizeof(enum attr_type);
457 dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
462 attr_data_get(struct attr *attr)
464 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
466 if (attr->type == attr_order)
467 return &attr->u.range;
472 attr_data_set(struct attr *attr, void *data)
474 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
475 attr->u.num=*((int *)data);
481 attr_data_set_le(struct attr * attr, void * data)
483 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
484 attr->u.num=le32_to_cpu(*((int *)data));
485 else if (attr->type == attr_order) {
486 attr->u.num=le32_to_cpu(*((int *)data));
487 attr->u.range.min=le16_to_cpu(attr->u.range.min);
488 attr->u.range.max=le16_to_cpu(attr->u.range.max);
491 /* Fixme: Handle long long */
497 attr_free(struct attr *attr)
501 if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) &&
502 !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end))
503 g_free(attr->u.data);
508 attr_dup_content(struct attr *src, struct attr *dst)
512 if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end)
513 dst->u.num=src->u.num;
514 else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end)
515 dst->u.data=src->u.data;
517 size=attr_data_size(src);
519 dst->u.data=g_malloc(size);
520 memcpy(dst->u.data, src->u.data, size);
526 attr_dup(struct attr *attr)
528 struct attr *ret=g_new0(struct attr, 1);
529 attr_dup_content(attr, ret);
534 attr_list_free(struct attr **attrs)
537 while (attrs && attrs[count]) {
538 attr_free(attrs[count++]);
544 attr_list_dup(struct attr **attrs)
546 struct attr **ret=attrs;
551 ret=g_new0(struct attr *, count+1);
552 for (i = 0 ; i < count ; i++)
553 ret[i]=attr_dup(attrs[i]);
559 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
564 dbg(1,"get_tag %s from %s\n", name, line);
584 if (*p == ' ' && !quoted)
590 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
593 strncpy(name_ret, n, len);
602 strncpy(val_ret, e, len);
613 attr_types_contains(enum attr_type *types, enum attr_type type)
615 while (types && *types != attr_none) {
624 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
629 return attr_types_contains(types, type);