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=(char *)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 return g_strdup_printf("(no text[%s])", attr_to_name(type));
269 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
271 dbg(1, "enter attrs=%p\n", attrs);
273 dbg(1,"*attrs=%p\n", *attrs);
274 if ((*attrs)->type == attr) {
283 attr_match(enum attr_type search, enum attr_type found)
296 return search == found;
301 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
303 while (attrs && *attrs) {
304 if (attr_match(type,(*attrs)->type)) {
308 if (*((void **)iter) < (void *)attrs) {
309 *((void **)iter)=(void *)attrs;
315 if (type == attr_any || type == attr_any_xml)
317 while (def_attrs && *def_attrs) {
318 if ((*def_attrs)->type == type) {
328 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
330 struct attr **curr=attrs;
332 while (curr && *curr) {
333 if ((*curr)->type == attr->type) {
335 *curr=attr_dup(attr);
341 curr=g_new0(struct attr *, count+2);
342 for (i = 0 ; i < count ; i++)
344 curr[count]=attr_dup(attr);
351 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
353 struct attr **curr=attrs;
355 while (curr && *curr) {
359 curr=g_new0(struct attr *, count+2);
360 for (i = 0 ; i < count ; i++)
362 curr[count]=attr_dup(attr);
369 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
371 struct attr **curr=attrs;
372 int i,j,count=0,found=0;
373 while (curr && *curr) {
374 if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data)
381 curr=g_new0(struct attr *, count);
383 for (i = 0 ; i < count ; i++) {
384 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
395 attr_type_begin(enum attr_type type)
397 if (type < attr_type_item_begin)
399 if (type < attr_type_int_begin)
400 return attr_type_item_begin;
401 if (type < attr_type_string_begin)
402 return attr_type_int_begin;
403 if (type < attr_type_special_begin)
404 return attr_type_string_begin;
405 if (type < attr_type_double_begin)
406 return attr_type_special_begin;
407 if (type < attr_type_coord_geo_begin)
408 return attr_type_double_begin;
409 if (type < attr_type_color_begin)
410 return attr_type_coord_geo_begin;
411 if (type < attr_type_object_begin)
412 return attr_type_color_begin;
413 if (type < attr_type_coord_begin)
414 return attr_type_object_begin;
415 if (type < attr_type_pcoord_begin)
416 return attr_type_coord_begin;
417 if (type < attr_type_callback_begin)
418 return attr_type_pcoord_begin;
419 if (type < attr_type_int64_begin)
420 return attr_type_callback_begin;
421 if (type <= attr_type_int64_end)
422 return attr_type_int64_begin;
427 attr_data_size(struct attr *attr)
429 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end)
430 return strlen(attr->u.str)+1;
431 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
432 return sizeof(attr->u.num);
433 if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end)
434 return sizeof(*attr->u.coord_geo);
435 if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end)
436 return sizeof(*attr->u.color);
437 if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end)
438 return sizeof(void *);
439 if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end)
440 return sizeof(*attr->u.num64);
441 if (attr->type == attr_order)
442 return sizeof(attr->u.range);
443 if (attr->type == attr_item_types) {
445 while (attr->u.item_types[i++] != type_none);
446 return i*sizeof(enum item_type);
448 if (attr->type == attr_attr_types) {
450 while (attr->u.attr_types[i++] != attr_none);
451 return i*sizeof(enum attr_type);
453 dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
458 attr_data_get(struct attr *attr)
460 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
462 if (attr->type == attr_order)
463 return &attr->u.range;
468 attr_data_set(struct attr *attr, void *data)
470 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
471 attr->u.num=*((int *)data);
477 attr_data_set_le(struct attr * attr, void * data)
479 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
480 attr->u.num=le32_to_cpu(*((int *)data));
481 else if (attr->type == attr_order) {
482 attr->u.num=le32_to_cpu(*((int *)data));
483 attr->u.range.min=le16_to_cpu(attr->u.range.min);
484 attr->u.range.max=le16_to_cpu(attr->u.range.max);
487 /* Fixme: Handle long long */
493 attr_free(struct attr *attr)
497 if (attr->type == attr_position_coord_geo)
498 g_free(attr->u.coord_geo);
499 if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end)
500 g_free(attr->u.color);
505 attr_dup(struct attr *attr)
508 struct attr *ret=g_new0(struct attr, 1);
509 ret->type=attr->type;
510 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
511 ret->u.num=attr->u.num;
512 else if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end)
513 ret->u.data=attr->u.data;
515 size=attr_data_size(attr);
517 ret->u.data=g_malloc(size);
518 memcpy(ret->u.data, attr->u.data, size);
525 attr_list_free(struct attr **attrs)
528 while (attrs && attrs[count]) {
529 attr_free(attrs[count++]);
535 attr_list_dup(struct attr **attrs)
537 struct attr **ret=attrs;
542 ret=g_new0(struct attr *, count+1);
543 for (i = 0 ; i < count ; i++)
544 ret[i]=attr_dup(attrs[i]);
550 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
555 dbg(1,"get_tag %s from %s\n", name, line);
575 if (*p == ' ' && !quoted)
581 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
584 strncpy(name_ret, n, len);
593 strncpy(val_ret, e, len);
604 attr_types_contains(enum attr_type *types, enum attr_type type)
606 while (types && *types != attr_none) {
615 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
620 return attr_types_contains(types, type);