Recreate the navit git/gerrit project that vanished
[profile/ivi/navit.git] / navit / attr.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include "debug.h"
25 #include "item.h"
26 #include "coord.h"
27 #include "transform.h"
28 #include "color.h"
29 #include "attr.h"
30 #include "map.h"
31 #include "config.h"
32 #include "endianess.h"
33 #include "util.h"
34 #include "types.h"
35 #include "xmlconfig.h"
36
37 struct attr_name {
38         enum attr_type attr;
39         char *name;
40 };
41
42
43 static struct attr_name attr_names[]={
44 #define ATTR2(x,y) ATTR(y)
45 #define ATTR(x) { attr_##x, #x },
46 #include "attr_def.h"
47 #undef ATTR2
48 #undef ATTR
49 };
50
51 enum attr_type
52 attr_from_name(const char *name)
53 {
54         int i;
55
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;
59         }
60         return attr_none;
61 }
62
63
64 static int attr_match(enum attr_type search, enum attr_type found);
65
66
67
68 char *
69 attr_to_name(enum attr_type attr)
70 {
71         int i;
72
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;
76         }
77         return NULL; 
78 }
79
80 struct attr *
81 attr_new_from_text(const char *name, const char *value)
82 {
83         enum attr_type attr;
84         struct attr *ret;
85         struct coord_geo *g;
86         struct coord c;
87         char *pos,*type_str,*str,*tok;
88         int min,max,count;
89
90         ret=g_new0(struct attr, 1);
91         dbg(1,"enter name='%s' value='%s'\n", name, value);
92         attr=attr_from_name(name);
93         ret->type=attr;
94         switch (attr) {
95         case attr_item_type:
96                 ret->u.item_type=item_from_name(value);
97                 break;
98         case attr_item_types:
99                 count=0;
100                 type_str=g_strdup(value);
101                 str=type_str;
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;
106                         str=NULL;
107                 }
108                 g_free(type_str);
109                 break;
110         case attr_attr_types:
111                 count=0;
112                 type_str=g_strdup(value);
113                 str=type_str;
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;
118                         str=NULL;
119                 }
120                 g_free(type_str);
121                 break;
122         case attr_dash:
123                 count=0;
124                 type_str=g_strdup(value);
125                 str=type_str;
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;
130                         str=NULL;
131                 }
132                 g_free(type_str);
133                 break;
134         case attr_order:
135         case attr_sequence_range:
136         case attr_angle_range:
137         case attr_speed_range:
138                 pos=strchr(value, '-');
139                 min=0;
140                 max=32767;
141                 if (! pos) {
142                         sscanf(value,"%d",&min);
143                         max=min;
144                 } else if (pos == value)
145                         sscanf(value,"-%d",&max);
146                 else
147                         sscanf(value,"%d-%d",&min, &max);
148                 ret->u.range.min=min;
149                 ret->u.range.max=max;
150                 break;
151         default:
152                 if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
153                         ret->u.str=g_strdup(value);
154                         break;
155                 }
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);
159                         else
160                                 ret->u.num=strtol(value, NULL, 0);
161                         
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);
168                                         }
169
170                                         ret->u.num += 0x60000000;
171                                 } else {
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);
174                                         }
175                                 }
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")) 
178                                         ret->u.num=1;
179                                 else
180                                         ret->u.num=0;
181                         }
182                         break;
183                 }
184                 if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
185                         struct color *color=g_new0(struct color, 1);
186                         int r,g,b,a;
187                         ret->u.color=color;
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;
193                                 color->a = (65535);
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;
200                         } else {
201                                 dbg(0,"color %s has unknown format\n",value);
202                         }
203                         break;
204                 }
205                 if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) {
206                         g=g_new(struct coord_geo, 1);
207                         ret->u.coord_geo=g;
208                         coord_parse(value, projection_mg, &c);
209                         transform_to_geo(projection_mg, &c, g);
210                         break;
211                 }
212                 dbg(1,"default\n");
213                 g_free(ret);
214                 ret=NULL;
215         }
216         return ret;
217 }
218
219 static char *
220 flags_to_text(int flags)
221 {
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?"|":"");
255         return ret;
256 }
257
258 char *
259 attr_to_text(struct attr *attr, struct map *map, int pretty)
260 {
261         char *ret;
262         enum attr_type type=attr->type;
263
264         if (type >= attr_type_item_begin && type <= attr_type_item_end) {
265                 struct item *item=attr->u.item;
266                 struct attr type, data;
267                 if (! item)
268                         return g_strdup("(nil)");
269                 if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL))
270                         type.u.str="";
271                 if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL))
272                         data.u.str="";
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);
274         }
275         if (type >= attr_type_string_begin && type <= attr_type_string_end) {
276                 if (map) {
277                         char *mstr;
278                         if (attr->u.str) {
279                                 mstr=map_convert_string(map, attr->u.str);
280                                 ret=g_strdup(mstr);
281                                 map_convert_free(mstr);
282                         } else
283                                 ret=g_strdup("(null)");
284                         
285                 } else
286                         ret=g_strdup(attr->u.str);
287                 return ret;
288         }
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);
302                 else
303                         return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8);
304         }
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]);
310         }
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]);
314         }
315         if (type >= attr_type_group_begin && type <= attr_type_group_end) {
316                 int i=0;
317                 char *ret=g_strdup("");
318                 char *sep="";
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);
322                         g_free(val);
323                         sep=" ";
324                         i++;
325                 }
326                 return ret;
327         }
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));
330         }
331         return g_strdup_printf("(no text[%s])", attr_to_name(type));    
332 }
333
334 struct attr *
335 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
336 {
337         dbg(1, "enter attrs=%p\n", attrs);
338         while (*attrs) {
339                 dbg(1,"*attrs=%p\n", *attrs);
340                 if ((*attrs)->type == attr) {
341                         return *attrs;
342                 }
343                 attrs++;
344         }
345         return NULL;
346 }
347
348 static int
349 attr_match(enum attr_type search, enum attr_type found)
350 {
351         switch (search) {
352         case attr_any:
353                 return 1;
354         case attr_any_xml:
355                 switch (found) {
356                 case attr_callback:
357                         return 0;
358                 default:
359                         return 1;
360                 }
361         default:
362                 return search == found;
363         }
364 }
365
366 int
367 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
368 {
369         while (attrs && *attrs) {
370                 if (attr_match(type,(*attrs)->type)) {
371                         *attr=**attrs;
372                         if (!iter)
373                                 return 1;
374                         if (*((void **)iter) < (void *)attrs) {
375                                 *((void **)iter)=(void *)attrs;
376                                 return 1;
377                         }
378                 }
379                 attrs++;
380         }
381         if (type == attr_any || type == attr_any_xml)
382                 return 0;
383         while (def_attrs && *def_attrs) {
384                 if ((*def_attrs)->type == type) {
385                         *attr=**def_attrs;
386                         return 1;
387                 }
388                 def_attrs++;
389         }
390         return 0;
391 }
392
393 struct attr **
394 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
395 {
396         struct attr **curr=attrs;
397         int i,count=0;
398         while (curr && *curr) {
399                 if ((*curr)->type == attr->type) {
400                         attr_free(*curr);
401                         *curr=attr_dup(attr);
402                         return attrs;
403                 }
404                 curr++;
405                 count++;
406         }
407         curr=g_new0(struct attr *, count+2);
408         for (i = 0 ; i < count ; i++)
409                 curr[i]=attrs[i];
410         curr[count]=attr_dup(attr);
411         curr[count+1]=NULL;
412         g_free(attrs);
413         return curr;
414 }
415
416 struct attr **
417 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
418 {
419         struct attr **curr=attrs;
420         int i,count=0;
421         while (curr && *curr) {
422                 curr++;
423                 count++;
424         }
425         curr=g_new0(struct attr *, count+2);
426         for (i = 0 ; i < count ; i++)
427                 curr[i]=attrs[i];
428         curr[count]=attr_dup(attr);
429         curr[count+1]=NULL;
430         g_free(attrs);
431         return curr;
432 }
433
434 struct attr **
435 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
436 {
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)
441                         found=1;
442                 curr++;
443                 count++;
444         }
445         if (!found)
446                 return attrs;
447         curr=g_new0(struct attr *, count);
448         j=0;
449         for (i = 0 ; i < count ; i++) {
450                 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
451                         curr[j++]=attrs[i];
452                 else
453                         attr_free(attrs[i]);
454         }
455         curr[j]=NULL;
456         g_free(attrs);
457         return curr;
458 }
459
460 enum attr_type
461 attr_type_begin(enum attr_type type)
462 {
463         if (type < attr_type_item_begin)
464                 return attr_none;
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;
489         return attr_none;
490 }
491
492 int
493 attr_data_size(struct attr *attr)
494 {
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) {
514                 int i=0;
515                 while (attr->u.item_types[i++] != type_none);
516                 return i*sizeof(enum item_type);
517         }
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) {
521                 int i=0;
522                 while (attr->u.attr_types[i++] != attr_none);
523                 return i*sizeof(enum attr_type);
524         }
525         dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
526         return 0;
527 }
528
529 void *
530 attr_data_get(struct attr *attr)
531 {
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))
534                 return &attr->u.num;
535         if (attr->type == attr_order)
536                 return &attr->u.range;
537         return attr->u.data;
538 }
539
540 void
541 attr_data_set(struct attr *attr, void *data)
542 {
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);
546         else
547                 attr->u.data=data;
548 }
549
550 void
551 attr_data_set_le(struct attr * attr, void * data)
552 {
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);
560         }
561         else
562 /* Fixme: Handle long long */
563                 attr->u.data=data;
564
565 }
566
567 void
568 attr_free(struct attr *attr)
569 {
570         if (!attr)
571                 return;
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);
576         }
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);
580         g_free(attr);
581 }
582
583 void
584 attr_dup_content(struct attr *src, struct attr *dst)
585 {
586         int size;
587         dst->type=src->type;
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);
595                         } else
596                                 dst->u.data=obj;
597                 } else 
598                         dst->u.data=src->u.data;
599         } else {
600                 size=attr_data_size(src);
601                 if (size) {
602                         dst->u.data=g_malloc(size);
603                         memcpy(dst->u.data, src->u.data, size);
604                 }
605         }
606 }
607
608 struct attr *
609 attr_dup(struct attr *attr)
610 {
611         struct attr *ret=g_new0(struct attr, 1);
612         attr_dup_content(attr, ret);
613         return ret;
614 }
615
616 void
617 attr_list_free(struct attr **attrs)
618 {
619         int count=0;
620         while (attrs && attrs[count]) {
621                 attr_free(attrs[count++]);
622         }
623         g_free(attrs);
624 }
625
626 struct attr **
627 attr_list_dup(struct attr **attrs)
628 {
629         struct attr **ret=attrs;
630         int i,count=0;
631
632         while (attrs[count])
633                 count++;
634         ret=g_new0(struct attr *, count+1);
635         for (i = 0 ; i < count ; i++)
636                 ret[i]=attr_dup(attrs[i]);
637         return ret;
638 }
639
640
641 int
642 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
643 {
644         int len=0,quoted;
645         char *p,*e,*n;
646
647         dbg(1,"get_tag %s from %s\n", name, line); 
648         if (name)
649                 len=strlen(name);
650         if (pos) 
651                 p=line+*pos;
652         else
653                 p=line;
654         for(;;) {
655                 while (*p == ' ') {
656                         p++;
657                 }
658                 if (! *p)
659                         return 0;
660                 n=p;
661                 e=strchr(p,'=');
662                 if (! e)
663                         return 0;
664                 p=e+1;
665                 quoted=0;
666                 while (*p) {
667                         if (*p == ' ' && !quoted)
668                                 break;
669                         if (*p == '"')
670                                 quoted=1-quoted;
671                         p++;
672                 }
673                 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
674                         if (name_ret) {
675                                 len=e-n;
676                                 strncpy(name_ret, n, len);
677                                 name_ret[len]='\0';
678                         }
679                         e++;
680                         len=p-e;
681                         if (e[0] == '"') {
682                                 e++;
683                                 len-=2;
684                         }
685                         strncpy(val_ret, e, len);
686                         val_ret[len]='\0';
687                         if (pos)
688                                 *pos=p-line;
689                         return 1;
690                 }
691         }       
692         return 0;
693 }
694
695 /**
696  * Check if an enumeration of attribute types contains a specific attribute.
697  *
698  * @param types Pointer to the attr_type enumeration to be searched
699  * @param type The attr_type to be searched for
700  *
701  * @return 1 if the attribute type was found, 0 if it was not found or if a null pointer was passed as types
702  */
703 int
704 attr_types_contains(enum attr_type *types, enum attr_type type)
705 {
706         while (types && *types != attr_none) {
707                 if (*types == type)
708                         return 1;
709                 types++;
710         }
711         return 0;
712 }
713
714 /**
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.
717  *
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.
721  *
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.
723  */
724 int
725 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
726 {
727         if (!types) {
728                 return deflt;
729         }
730         return attr_types_contains(types, type);        
731 }