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"
35 #include "xmlconfig.h"
43 static struct attr_name attr_names[]={
44 #define ATTR2(x,y) ATTR(y)
45 #define ATTR(x) { attr_##x, #x },
52 attr_from_name(const char *name)
56 for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
57 if (! strcmp(attr_names[i].name, name))
58 return attr_names[i].attr;
64 static int attr_match(enum attr_type search, enum attr_type found);
69 attr_to_name(enum attr_type attr)
73 for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
74 if (attr_names[i].attr == attr)
75 return attr_names[i].name;
81 attr_new_from_text(const char *name, const char *value)
87 char *pos,*type_str,*str,*tok;
90 ret=g_new0(struct attr, 1);
91 dbg(1,"enter name='%s' value='%s'\n", name, value);
92 attr=attr_from_name(name);
96 ret->u.item_type=item_from_name(value);
100 type_str=g_strdup(value);
102 while ((tok=strtok(str, ","))) {
103 ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type));
104 ret->u.item_types[count++]=item_from_name(tok);
105 ret->u.item_types[count]=type_none;
110 case attr_attr_types:
112 type_str=g_strdup(value);
114 while ((tok=strtok(str, ","))) {
115 ret->u.attr_types=g_realloc(ret->u.attr_types, (count+2)*sizeof(enum attr_type));
116 ret->u.attr_types[count++]=attr_from_name(tok);
117 ret->u.attr_types[count]=attr_none;
124 type_str=g_strdup(value);
126 while ((tok=strtok(str, ","))) {
127 ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int));
128 ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0);
129 ret->u.dash[count]=0;
135 case attr_sequence_range:
136 case attr_angle_range:
137 case attr_speed_range:
138 pos=strchr(value, '-');
142 sscanf(value,"%d",&min);
144 } else if (pos == value)
145 sscanf(value,"-%d",&max);
147 sscanf(value,"%d-%d",&min, &max);
148 ret->u.range.min=min;
149 ret->u.range.max=max;
152 if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
153 ret->u.str=g_strdup(value);
156 if (attr >= attr_type_int_begin && attr <= attr_type_int_end) {
157 if (value[0] == '0' && value[1] == 'x')
158 ret->u.num=strtoul(value, NULL, 0);
160 ret->u.num=strtol(value, NULL, 0);
162 if ((attr >= attr_type_rel_abs_begin) && (attr < attr_type_boolean_begin)) {
163 /* Absolute values are from -0x40000000 - 0x40000000, with 0x0 being 0 (who would have thought that?)
164 Relative values are from 0x40000001 - 0x80000000, with 0x60000000 being 0 */
165 if (strchr(value, '%')) {
166 if ((ret->u.num > 0x20000000) || (ret->u.num < -0x1FFFFFFF)) {
167 dbg(0, "Relative possibly-relative attribute with invalid value %i\n", ret->u.num);
170 ret->u.num += 0x60000000;
172 if ((ret->u.num > 0x40000000) || (ret->u.num < -0x40000000)) {
173 dbg(0, "Non-relative possibly-relative attribute with invalid value %i\n", ret->u.num);
176 } else if (attr >= attr_type_boolean_begin) { // also check for yes and no
177 if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false"))
184 if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
185 struct color *color=g_new0(struct color, 1);
188 if(strlen(value)==7){
189 sscanf(value,"#%02x%02x%02x", &r, &g, &b);
190 color->r = (r << 8) | r;
191 color->g = (g << 8) | g;
192 color->b = (b << 8) | b;
194 } else if(strlen(value)==9){
195 sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a);
196 color->r = (r << 8) | r;
197 color->g = (g << 8) | g;
198 color->b = (b << 8) | b;
199 color->a = (a << 8) | a;
201 dbg(0,"color %s has unknown format\n",value);
205 if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) {
206 g=g_new(struct coord_geo, 1);
208 coord_parse(value, projection_mg, &c);
209 transform_to_geo(projection_mg, &c, g);
220 flags_to_text(int flags)
222 char *ret=g_strdup_printf("0x%x:",flags);
223 if (flags & AF_ONEWAY) ret=g_strconcat_printf(ret,"%sAF_ONEWAY",ret?"|":"");
224 if (flags & AF_ONEWAYREV) ret=g_strconcat_printf(ret,"%sAF_ONEWAYREV",ret?"|":"");
225 if (flags & AF_SEGMENTED) ret=g_strconcat_printf(ret,"%sAF_SEGMENTED",ret?"|":"");
226 if (flags & AF_ROUNDABOUT) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT",ret?"|":"");
227 if (flags & AF_ROUNDABOUT_VALID) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT_VALID",ret?"|":"");
228 if (flags & AF_ONEWAY_EXCEPTION) ret=g_strconcat_printf(ret,"%sAF_ONEWAY_EXCEPTION",ret?"|":"");
229 if (flags & AF_SPEED_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SPEED_LIMIT",ret?"|":"");
230 if (flags & AF_RESERVED1) ret=g_strconcat_printf(ret,"%sAF_RESERVED1",ret?"|":"");
231 if (flags & AF_SIZE_OR_WEIGHT_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SIZE_OR_WEIGHT_LIMIT",ret?"|":"");
232 if (flags & AF_THROUGH_TRAFFIC_LIMIT) ret=g_strconcat_printf(ret,"%sAF_THROUGH_TRAFFIC_LIMIT",ret?"|":"");
233 if (flags & AF_TOLL) ret=g_strconcat_printf(ret,"%sAF_TOLL",ret?"|":"");
234 if (flags & AF_SEASONAL) ret=g_strconcat_printf(ret,"%sAF_SEASONAL",ret?"|":"");
235 if (flags & AF_UNPAVED) ret=g_strconcat_printf(ret,"%sAF_UNPAVED",ret?"|":"");
236 if (flags & AF_FORD) ret=g_strconcat_printf(ret,"%sAF_FORD",ret?"|":"");
237 if (flags & AF_UNDERGROUND) ret=g_strconcat_printf(ret,"%sAF_UNDERGROUND",ret?"|":"");
238 if (flags & AF_DANGEROUS_GOODS) ret=g_strconcat_printf(ret,"%sAF_DANGEROUS_GOODS",ret?"|":"");
239 if ((flags & AF_ALL) == AF_ALL)
240 return g_strconcat_printf(ret,"%sAF_ALL",ret?"|":"");
241 if ((flags & AF_ALL) == AF_MOTORIZED_FAST)
242 return g_strconcat_printf(ret,"%sAF_MOTORIZED_FAST",ret?"|":"");
243 if (flags & AF_EMERGENCY_VEHICLES) ret=g_strconcat_printf(ret,"%sAF_EMERGENCY_VEHICLES",ret?"|":"");
244 if (flags & AF_TRANSPORT_TRUCK) ret=g_strconcat_printf(ret,"%sAF_TRANSPORT_TRUCK",ret?"|":"");
245 if (flags & AF_DELIVERY_TRUCK) ret=g_strconcat_printf(ret,"%sAF_DELIVERY_TRUCK",ret?"|":"");
246 if (flags & AF_PUBLIC_BUS) ret=g_strconcat_printf(ret,"%sAF_PUBLIC_BUS",ret?"|":"");
247 if (flags & AF_TAXI) ret=g_strconcat_printf(ret,"%sAF_TAXI",ret?"|":"");
248 if (flags & AF_HIGH_OCCUPANCY_CAR) ret=g_strconcat_printf(ret,"%sAF_HIGH_OCCUPANCY_CAR",ret?"|":"");
249 if (flags & AF_CAR) ret=g_strconcat_printf(ret,"%sAF_CAR",ret?"|":"");
250 if (flags & AF_MOTORCYCLE) ret=g_strconcat_printf(ret,"%sAF_MOTORCYCLE",ret?"|":"");
251 if (flags & AF_MOPED) ret=g_strconcat_printf(ret,"%sAF_MOPED",ret?"|":"");
252 if (flags & AF_HORSE) ret=g_strconcat_printf(ret,"%sAF_HORSE",ret?"|":"");
253 if (flags & AF_BIKE) ret=g_strconcat_printf(ret,"%sAF_BIKE",ret?"|":"");
254 if (flags & AF_PEDESTRIAN) ret=g_strconcat_printf(ret,"%sAF_PEDESTRIAN",ret?"|":"");
259 attr_to_text(struct attr *attr, struct map *map, int pretty)
262 enum attr_type type=attr->type;
264 if (type >= attr_type_item_begin && type <= attr_type_item_end) {
265 struct item *item=attr->u.item;
266 struct attr type, data;
268 return g_strdup("(nil)");
269 if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL))
271 if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL))
273 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);
275 if (type >= attr_type_string_begin && type <= attr_type_string_end) {
279 mstr=map_convert_string(map, attr->u.str);
281 map_convert_free(mstr);
283 ret=g_strdup("(null)");
286 ret=g_strdup(attr->u.str);
289 if (type == attr_flags || type == attr_through_traffic_flags)
290 return flags_to_text(attr->u.num);
291 if (type >= attr_type_int_begin && type <= attr_type_int_end)
292 return g_strdup_printf("%ld", attr->u.num);
293 if (type >= attr_type_int64_begin && type <= attr_type_int64_end)
294 return g_strdup_printf(LONGLONG_FMT, *attr->u.num64);
295 if (type >= attr_type_double_begin && type <= attr_type_double_end)
296 return g_strdup_printf("%f", *attr->u.numd);
297 if (type >= attr_type_object_begin && type <= attr_type_object_end)
298 return g_strdup_printf("(object[%s])", attr_to_name(type));
299 if (type >= attr_type_color_begin && type <= attr_type_color_end) {
300 if (attr->u.color->a != 65535)
301 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);
303 return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8);
305 if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end)
306 return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat);
307 if (type == attr_zipfile_ref_block) {
308 int *data=attr->u.data;
309 return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]);
311 if (type == attr_item_id) {
312 int *data=attr->u.data;
313 return g_strdup_printf("0x%x,0x%x",data[0],data[1]);
315 if (type >= attr_type_group_begin && type <= attr_type_group_end) {
317 char *ret=g_strdup("");
319 while (attr->u.attrs[i].type) {
320 char *val=attr_to_text(&attr->u.attrs[i], map, pretty);
321 ret=g_strconcat_printf(ret,"%s%s=%s",sep,attr_to_name(attr->u.attrs[i].type),val);
328 if (type >= attr_type_item_type_begin && type <= attr_type_item_type_end) {
329 return g_strdup_printf("0x%ld[%s]",attr->u.num,item_to_name(attr->u.num));
331 return g_strdup_printf("(no text[%s])", attr_to_name(type));
335 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
337 dbg(1, "enter attrs=%p\n", attrs);
339 dbg(1,"*attrs=%p\n", *attrs);
340 if ((*attrs)->type == attr) {
349 attr_match(enum attr_type search, enum attr_type found)
362 return search == found;
367 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
369 while (attrs && *attrs) {
370 if (attr_match(type,(*attrs)->type)) {
374 if (*((void **)iter) < (void *)attrs) {
375 *((void **)iter)=(void *)attrs;
381 if (type == attr_any || type == attr_any_xml)
383 while (def_attrs && *def_attrs) {
384 if ((*def_attrs)->type == type) {
394 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
396 struct attr **curr=attrs;
398 while (curr && *curr) {
399 if ((*curr)->type == attr->type) {
401 *curr=attr_dup(attr);
407 curr=g_new0(struct attr *, count+2);
408 for (i = 0 ; i < count ; i++)
410 curr[count]=attr_dup(attr);
417 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
419 struct attr **curr=attrs;
421 while (curr && *curr) {
425 curr=g_new0(struct attr *, count+2);
426 for (i = 0 ; i < count ; i++)
428 curr[count]=attr_dup(attr);
435 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
437 struct attr **curr=attrs;
438 int i,j,count=0,found=0;
439 while (curr && *curr) {
440 if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data)
447 curr=g_new0(struct attr *, count);
449 for (i = 0 ; i < count ; i++) {
450 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
461 attr_type_begin(enum attr_type type)
463 if (type < attr_type_item_begin)
465 if (type < attr_type_int_begin)
466 return attr_type_item_begin;
467 if (type < attr_type_string_begin)
468 return attr_type_int_begin;
469 if (type < attr_type_special_begin)
470 return attr_type_string_begin;
471 if (type < attr_type_double_begin)
472 return attr_type_special_begin;
473 if (type < attr_type_coord_geo_begin)
474 return attr_type_double_begin;
475 if (type < attr_type_color_begin)
476 return attr_type_coord_geo_begin;
477 if (type < attr_type_object_begin)
478 return attr_type_color_begin;
479 if (type < attr_type_coord_begin)
480 return attr_type_object_begin;
481 if (type < attr_type_pcoord_begin)
482 return attr_type_coord_begin;
483 if (type < attr_type_callback_begin)
484 return attr_type_pcoord_begin;
485 if (type < attr_type_int64_begin)
486 return attr_type_callback_begin;
487 if (type <= attr_type_int64_end)
488 return attr_type_int64_begin;
493 attr_data_size(struct attr *attr)
495 if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end)
496 return strlen(attr->u.str)+1;
497 if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end)
498 return sizeof(attr->u.num);
499 if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end)
500 return sizeof(*attr->u.coord_geo);
501 if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end)
502 return sizeof(*attr->u.color);
503 if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end)
504 return sizeof(void *);
505 if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end)
506 return sizeof(struct item);
507 if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end)
508 return sizeof(*attr->u.num64);
509 if (attr->type == attr_order)
510 return sizeof(attr->u.range);
511 if (attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end)
512 return sizeof(*attr->u.numd);
513 if (attr->type == attr_item_types) {
515 while (attr->u.item_types[i++] != type_none);
516 return i*sizeof(enum item_type);
518 if (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)
519 return sizeof(enum item_type);
520 if (attr->type == attr_attr_types) {
522 while (attr->u.attr_types[i++] != attr_none);
523 return i*sizeof(enum attr_type);
525 dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
530 attr_data_get(struct attr *attr)
532 if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) ||
533 (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end))
535 if (attr->type == attr_order)
536 return &attr->u.range;
541 attr_data_set(struct attr *attr, void *data)
543 if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) ||
544 (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end))
545 attr->u.num=*((int *)data);
551 attr_data_set_le(struct attr * attr, void * data)
553 if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) ||
554 (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end))
555 attr->u.num=le32_to_cpu(*((int *)data));
556 else if (attr->type == attr_order) {
557 attr->u.num=le32_to_cpu(*((int *)data));
558 attr->u.range.min=le16_to_cpu(attr->u.range.min);
559 attr->u.range.max=le16_to_cpu(attr->u.range.max);
562 /* Fixme: Handle long long */
568 attr_free(struct attr *attr)
572 if (attr->type == attr_navit || attr->type == attr_vehicle) {
573 struct navit_object *obj=attr->u.data;
574 if (obj && obj->func && obj->func->unref)
575 obj->func->unref(obj);
577 if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) &&
578 !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end))
579 g_free(attr->u.data);
584 attr_dup_content(struct attr *src, struct attr *dst)
588 if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end)
589 dst->u.num=src->u.num;
590 else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) {
591 if (src->type == attr_navit || src->type == attr_vehicle) {
592 struct navit_object *obj=src->u.data;
593 if (obj && obj->func && obj->func->ref) {
594 dst->u.data=obj->func->ref(obj);
598 dst->u.data=src->u.data;
600 size=attr_data_size(src);
602 dst->u.data=g_malloc(size);
603 memcpy(dst->u.data, src->u.data, size);
609 attr_dup(struct attr *attr)
611 struct attr *ret=g_new0(struct attr, 1);
612 attr_dup_content(attr, ret);
617 attr_list_free(struct attr **attrs)
620 while (attrs && attrs[count]) {
621 attr_free(attrs[count++]);
627 attr_list_dup(struct attr **attrs)
629 struct attr **ret=attrs;
634 ret=g_new0(struct attr *, count+1);
635 for (i = 0 ; i < count ; i++)
636 ret[i]=attr_dup(attrs[i]);
642 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
647 dbg(1,"get_tag %s from %s\n", name, line);
667 if (*p == ' ' && !quoted)
673 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
676 strncpy(name_ret, n, len);
685 strncpy(val_ret, e, len);
696 * Check if an enumeration of attribute types contains a specific attribute.
698 * @param types Pointer to the attr_type enumeration to be searched
699 * @param type The attr_type to be searched for
701 * @return 1 if the attribute type was found, 0 if it was not found or if a null pointer was passed as types
704 attr_types_contains(enum attr_type *types, enum attr_type type)
706 while (types && *types != attr_none) {
715 * Check if an enumeration of attribute types contains a specific attribute.
716 * It is different from attr_types_contains in that it returns a caller-defined value if the pointer to the enumeration is NULL.
718 * @param types Pointer to the attr_type enumeration to be searched
719 * @param type The attr_type to be searched for
720 * @param deflt The default value to return if types is NULL.
722 * @return 1 if the attribute type was found, 0 if it was not found, the value of the deflt argument if types is NULL.
725 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
730 return attr_types_contains(types, type);