Fix:map_csv:Disable default notification of each deleted item.
[profile/ivi/navit.git] / navit / 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 static GHashTable *attr_hash;
52
53 void
54 attr_create_hash(void)
55 {
56         int i;
57         attr_hash=g_hash_table_new(g_str_hash, g_str_equal);
58         for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
59                 g_hash_table_insert(attr_hash, attr_names[i].name, GINT_TO_POINTER(attr_names[i].attr));
60         }
61 }
62
63 void
64 attr_destroy_hash(void)
65 {
66         g_hash_table_destroy(attr_hash);
67         attr_hash=NULL;
68 }
69
70 enum attr_type
71 attr_from_name(const char *name)
72 {
73         int i;
74
75         if (attr_hash)
76                 return GPOINTER_TO_INT(g_hash_table_lookup(attr_hash, name));
77         for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
78                 if (! strcmp(attr_names[i].name, name))
79                         return attr_names[i].attr;
80         }
81         return attr_none;
82 }
83
84
85 static int attr_match(enum attr_type search, enum attr_type found);
86
87
88
89 char *
90 attr_to_name(enum attr_type attr)
91 {
92         int i;
93
94         for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) {
95                 if (attr_names[i].attr == attr)
96                         return attr_names[i].name;
97         }
98         return NULL; 
99 }
100
101 struct attr *
102 attr_new_from_text(const char *name, const char *value)
103 {
104         enum attr_type attr;
105         struct attr *ret;
106         struct coord_geo *g;
107         struct coord c;
108         char *pos,*type_str,*str,*tok;
109         int min,max,count;
110
111         ret=g_new0(struct attr, 1);
112         dbg(1,"enter name='%s' value='%s'\n", name, value);
113         attr=attr_from_name(name);
114         ret->type=attr;
115         switch (attr) {
116         case attr_item_type:
117                 ret->u.item_type=item_from_name(value);
118                 break;
119         case attr_item_types:
120                 count=0;
121                 type_str=g_strdup(value);
122                 str=type_str;
123                 while ((tok=strtok(str, ","))) {
124                         ret->u.item_types=g_realloc(ret->u.item_types, (count+2)*sizeof(enum item_type));
125                         ret->u.item_types[count++]=item_from_name(tok);
126                         ret->u.item_types[count]=type_none;
127                         str=NULL;
128                 }
129                 g_free(type_str);
130                 break;
131         case attr_attr_types:
132                 count=0;
133                 type_str=g_strdup(value);
134                 str=type_str;
135                 while ((tok=strtok(str, ","))) {
136                         ret->u.attr_types=g_realloc(ret->u.attr_types, (count+2)*sizeof(enum attr_type));
137                         ret->u.attr_types[count++]=attr_from_name(tok);
138                         ret->u.attr_types[count]=attr_none;
139                         str=NULL;
140                 }
141                 g_free(type_str);
142                 break;
143         case attr_dash:
144                 count=0;
145                 type_str=g_strdup(value);
146                 str=type_str;
147                 while ((tok=strtok(str, ","))) {
148                         ret->u.dash=g_realloc(ret->u.dash, (count+2)*sizeof(int));
149                         ret->u.dash[count++]=g_ascii_strtoull(tok,NULL,0);
150                         ret->u.dash[count]=0;
151                         str=NULL;
152                 }
153                 g_free(type_str);
154                 break;
155         case attr_order:
156         case attr_sequence_range:
157         case attr_angle_range:
158         case attr_speed_range:
159                 pos=strchr(value, '-');
160                 min=0;
161                 max=32767;
162                 if (! pos) {
163                         sscanf(value,"%d",&min);
164                         max=min;
165                 } else if (pos == value)
166                         sscanf(value,"-%d",&max);
167                 else
168                         sscanf(value,"%d-%d",&min, &max);
169                 ret->u.range.min=min;
170                 ret->u.range.max=max;
171                 break;
172         default:
173                 if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
174                         ret->u.str=g_strdup(value);
175                         break;
176                 }
177                 if (attr >= attr_type_int_begin && attr <= attr_type_int_end) {
178                         if (value[0] == '0' && value[1] == 'x')
179                                 ret->u.num=strtoul(value, NULL, 0);
180                         else
181                                 ret->u.num=strtol(value, NULL, 0);
182                         
183                         if ((attr >= attr_type_rel_abs_begin) && (attr < attr_type_boolean_begin)) {
184                                 /* Absolute values are from -0x40000000 - 0x40000000, with 0x0 being 0 (who would have thought that?)
185                                          Relative values are from 0x40000001 - 0x80000000, with 0x60000000 being 0 */
186                                 if (strchr(value, '%')) {
187                                         if ((ret->u.num > 0x20000000) || (ret->u.num < -0x1FFFFFFF)) {
188                                                 dbg(0, "Relative possibly-relative attribute with invalid value %i\n", ret->u.num);
189                                         }
190
191                                         ret->u.num += 0x60000000;
192                                 } else {
193                                         if ((ret->u.num > 0x40000000) || (ret->u.num < -0x40000000)) {
194                                                 dbg(0, "Non-relative possibly-relative attribute with invalid value %i\n", ret->u.num);
195                                         }
196                                 }
197                         } else  if (attr >= attr_type_boolean_begin) { // also check for yes and no
198                                 if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false")) 
199                                         ret->u.num=1;
200                                 else
201                                         ret->u.num=0;
202                         }
203                         break;
204                 }
205                 if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
206                         struct color *color=g_new0(struct color, 1);
207                         int r,g,b,a;
208                         ret->u.color=color;
209                         if(strlen(value)==7){
210                                 sscanf(value,"#%02x%02x%02x", &r, &g, &b);
211                                 color->r = (r << 8) | r;
212                                 color->g = (g << 8) | g;
213                                 color->b = (b << 8) | b;
214                                 color->a = (65535);
215                         } else if(strlen(value)==9){
216                                 sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a);
217                                 color->r = (r << 8) | r;
218                                 color->g = (g << 8) | g;
219                                 color->b = (b << 8) | b;
220                                 color->a = (a << 8) | a;
221                         } else {
222                                 dbg(0,"color %s has unknown format\n",value);
223                         }
224                         break;
225                 }
226                 if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) {
227                         g=g_new(struct coord_geo, 1);
228                         ret->u.coord_geo=g;
229                         coord_parse(value, projection_mg, &c);
230                         transform_to_geo(projection_mg, &c, g);
231                         break;
232                 }
233                 dbg(1,"default\n");
234                 g_free(ret);
235                 ret=NULL;
236         }
237         return ret;
238 }
239
240 static char *
241 flags_to_text(int flags)
242 {
243         char *ret=g_strdup_printf("0x%x:",flags);
244         if (flags & AF_ONEWAY) ret=g_strconcat_printf(ret,"%sAF_ONEWAY",ret?"|":"");
245         if (flags & AF_ONEWAYREV) ret=g_strconcat_printf(ret,"%sAF_ONEWAYREV",ret?"|":"");
246         if (flags & AF_SEGMENTED) ret=g_strconcat_printf(ret,"%sAF_SEGMENTED",ret?"|":"");
247         if (flags & AF_ROUNDABOUT) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT",ret?"|":"");
248         if (flags & AF_ROUNDABOUT_VALID) ret=g_strconcat_printf(ret,"%sAF_ROUNDABOUT_VALID",ret?"|":"");
249         if (flags & AF_ONEWAY_EXCEPTION) ret=g_strconcat_printf(ret,"%sAF_ONEWAY_EXCEPTION",ret?"|":"");
250         if (flags & AF_SPEED_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SPEED_LIMIT",ret?"|":"");
251         if (flags & AF_RESERVED1) ret=g_strconcat_printf(ret,"%sAF_RESERVED1",ret?"|":"");
252         if (flags & AF_SIZE_OR_WEIGHT_LIMIT) ret=g_strconcat_printf(ret,"%sAF_SIZE_OR_WEIGHT_LIMIT",ret?"|":"");
253         if (flags & AF_THROUGH_TRAFFIC_LIMIT) ret=g_strconcat_printf(ret,"%sAF_THROUGH_TRAFFIC_LIMIT",ret?"|":"");
254         if (flags & AF_TOLL) ret=g_strconcat_printf(ret,"%sAF_TOLL",ret?"|":"");
255         if (flags & AF_SEASONAL) ret=g_strconcat_printf(ret,"%sAF_SEASONAL",ret?"|":"");
256         if (flags & AF_UNPAVED) ret=g_strconcat_printf(ret,"%sAF_UNPAVED",ret?"|":"");
257         if (flags & AF_FORD) ret=g_strconcat_printf(ret,"%sAF_FORD",ret?"|":"");
258         if (flags & AF_UNDERGROUND) ret=g_strconcat_printf(ret,"%sAF_UNDERGROUND",ret?"|":"");
259         if (flags & AF_DANGEROUS_GOODS) ret=g_strconcat_printf(ret,"%sAF_DANGEROUS_GOODS",ret?"|":"");
260         if ((flags & AF_ALL) == AF_ALL) 
261                 return g_strconcat_printf(ret,"%sAF_ALL",ret?"|":"");
262         if ((flags & AF_ALL) == AF_MOTORIZED_FAST) 
263                 return g_strconcat_printf(ret,"%sAF_MOTORIZED_FAST",ret?"|":"");
264         if (flags & AF_EMERGENCY_VEHICLES) ret=g_strconcat_printf(ret,"%sAF_EMERGENCY_VEHICLES",ret?"|":"");
265         if (flags & AF_TRANSPORT_TRUCK) ret=g_strconcat_printf(ret,"%sAF_TRANSPORT_TRUCK",ret?"|":"");
266         if (flags & AF_DELIVERY_TRUCK) ret=g_strconcat_printf(ret,"%sAF_DELIVERY_TRUCK",ret?"|":"");
267         if (flags & AF_PUBLIC_BUS) ret=g_strconcat_printf(ret,"%sAF_PUBLIC_BUS",ret?"|":"");
268         if (flags & AF_TAXI) ret=g_strconcat_printf(ret,"%sAF_TAXI",ret?"|":"");
269         if (flags & AF_HIGH_OCCUPANCY_CAR) ret=g_strconcat_printf(ret,"%sAF_HIGH_OCCUPANCY_CAR",ret?"|":"");
270         if (flags & AF_CAR) ret=g_strconcat_printf(ret,"%sAF_CAR",ret?"|":"");
271         if (flags & AF_MOTORCYCLE) ret=g_strconcat_printf(ret,"%sAF_MOTORCYCLE",ret?"|":"");
272         if (flags & AF_MOPED) ret=g_strconcat_printf(ret,"%sAF_MOPED",ret?"|":"");
273         if (flags & AF_HORSE) ret=g_strconcat_printf(ret,"%sAF_HORSE",ret?"|":"");
274         if (flags & AF_BIKE) ret=g_strconcat_printf(ret,"%sAF_BIKE",ret?"|":"");
275         if (flags & AF_PEDESTRIAN) ret=g_strconcat_printf(ret,"%sAF_PEDESTRIAN",ret?"|":"");
276         return ret;
277 }
278
279 char *
280 attr_to_text(struct attr *attr, struct map *map, int pretty)
281 {
282         char *ret;
283         enum attr_type type=attr->type;
284
285         if (type >= attr_type_item_begin && type <= attr_type_item_end) {
286                 struct item *item=attr->u.item;
287                 struct attr type, data;
288                 if (! item)
289                         return g_strdup("(nil)");
290                 if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL))
291                         type.u.str="";
292                 if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL))
293                         data.u.str="";
294                 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);
295         }
296         if (type >= attr_type_string_begin && type <= attr_type_string_end) {
297                 if (map) {
298                         char *mstr;
299                         if (attr->u.str) {
300                                 mstr=map_convert_string(map, attr->u.str);
301                                 ret=g_strdup(mstr);
302                                 map_convert_free(mstr);
303                         } else
304                                 ret=g_strdup("(null)");
305                         
306                 } else
307                         ret=g_strdup(attr->u.str);
308                 return ret;
309         }
310         if (type == attr_flags || type == attr_through_traffic_flags)
311                 return flags_to_text(attr->u.num);
312         if (type >= attr_type_int_begin && type <= attr_type_int_end) 
313                 return g_strdup_printf("%ld", attr->u.num);
314         if (type >= attr_type_int64_begin && type <= attr_type_int64_end) 
315                 return g_strdup_printf(LONGLONG_FMT, *attr->u.num64);
316         if (type >= attr_type_double_begin && type <= attr_type_double_end) 
317                 return g_strdup_printf("%f", *attr->u.numd);
318         if (type >= attr_type_object_begin && type <= attr_type_object_end) 
319                 return g_strdup_printf("(object[%s])", attr_to_name(type));
320         if (type >= attr_type_color_begin && type <= attr_type_color_end) {
321                 if (attr->u.color->a != 65535) 
322                         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);
323                 else
324                         return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8);
325         }
326         if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end) 
327                 return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat);
328         if (type == attr_zipfile_ref_block) {
329                 int *data=attr->u.data;
330                 return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]);
331         }
332         if (type == attr_item_id) {
333                 int *data=attr->u.data;
334                 return g_strdup_printf("0x%x,0x%x",data[0],data[1]);
335         }
336         if (type >= attr_type_group_begin && type <= attr_type_group_end) {
337                 int i=0;
338                 char *ret=g_strdup("");
339                 char *sep="";
340                 while (attr->u.attrs[i].type) {
341                         char *val=attr_to_text(&attr->u.attrs[i], map, pretty);
342                         ret=g_strconcat_printf(ret,"%s%s=%s",sep,attr_to_name(attr->u.attrs[i].type),val);
343                         g_free(val);
344                         sep=" ";
345                         i++;
346                 }
347                 return ret;
348         }
349         if (type >= attr_type_item_type_begin && type <= attr_type_item_type_end) {
350                 return g_strdup_printf("0x%ld[%s]",attr->u.num,item_to_name(attr->u.num));
351         }
352         return g_strdup_printf("(no text[%s])", attr_to_name(type));    
353 }
354
355 struct attr *
356 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
357 {
358         dbg(1, "enter attrs=%p\n", attrs);
359         while (*attrs) {
360                 dbg(1,"*attrs=%p\n", *attrs);
361                 if ((*attrs)->type == attr) {
362                         return *attrs;
363                 }
364                 attrs++;
365         }
366         return NULL;
367 }
368
369 static int
370 attr_match(enum attr_type search, enum attr_type found)
371 {
372         switch (search) {
373         case attr_any:
374                 return 1;
375         case attr_any_xml:
376                 switch (found) {
377                 case attr_callback:
378                         return 0;
379                 default:
380                         return 1;
381                 }
382         default:
383                 return search == found;
384         }
385 }
386
387 int
388 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
389 {
390         while (attrs && *attrs) {
391                 if (attr_match(type,(*attrs)->type)) {
392                         *attr=**attrs;
393                         if (!iter)
394                                 return 1;
395                         if (*((void **)iter) < (void *)attrs) {
396                                 *((void **)iter)=(void *)attrs;
397                                 return 1;
398                         }
399                 }
400                 attrs++;
401         }
402         if (type == attr_any || type == attr_any_xml)
403                 return 0;
404         while (def_attrs && *def_attrs) {
405                 if ((*def_attrs)->type == type) {
406                         *attr=**def_attrs;
407                         return 1;
408                 }
409                 def_attrs++;
410         }
411         return 0;
412 }
413
414 struct attr **
415 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
416 {
417         struct attr **curr=attrs;
418         int i,count=0;
419         while (curr && *curr) {
420                 if ((*curr)->type == attr->type) {
421                         attr_free(*curr);
422                         *curr=attr_dup(attr);
423                         return attrs;
424                 }
425                 curr++;
426                 count++;
427         }
428         curr=g_new0(struct attr *, count+2);
429         for (i = 0 ; i < count ; i++)
430                 curr[i]=attrs[i];
431         curr[count]=attr_dup(attr);
432         curr[count+1]=NULL;
433         g_free(attrs);
434         return curr;
435 }
436
437 struct attr **
438 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
439 {
440         struct attr **curr=attrs;
441         int i,count=0;
442         while (curr && *curr) {
443                 curr++;
444                 count++;
445         }
446         curr=g_new0(struct attr *, count+2);
447         for (i = 0 ; i < count ; i++)
448                 curr[i]=attrs[i];
449         curr[count]=attr_dup(attr);
450         curr[count+1]=NULL;
451         g_free(attrs);
452         return curr;
453 }
454
455 struct attr **
456 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
457 {
458         struct attr **curr=attrs;
459         int i,j,count=0,found=0;
460         while (curr && *curr) {
461                 if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data)
462                         found=1;
463                 curr++;
464                 count++;
465         }
466         if (!found)
467                 return attrs;
468         curr=g_new0(struct attr *, count);
469         j=0;
470         for (i = 0 ; i < count ; i++) {
471                 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
472                         curr[j++]=attrs[i];
473                 else
474                         attr_free(attrs[i]);
475         }
476         curr[j]=NULL;
477         g_free(attrs);
478         return curr;
479 }
480
481 enum attr_type
482 attr_type_begin(enum attr_type type)
483 {
484         if (type < attr_type_item_begin)
485                 return attr_none;
486         if (type < attr_type_int_begin)
487                 return attr_type_item_begin;
488         if (type < attr_type_string_begin)
489                 return attr_type_int_begin;
490         if (type < attr_type_special_begin)
491                 return attr_type_string_begin;
492         if (type < attr_type_double_begin)
493                 return attr_type_special_begin;
494         if (type < attr_type_coord_geo_begin)
495                 return attr_type_double_begin;
496         if (type < attr_type_color_begin)
497                 return attr_type_coord_geo_begin;
498         if (type < attr_type_object_begin)
499                 return attr_type_color_begin;
500         if (type < attr_type_coord_begin)
501                 return attr_type_object_begin;
502         if (type < attr_type_pcoord_begin)
503                 return attr_type_coord_begin;
504         if (type < attr_type_callback_begin)
505                 return attr_type_pcoord_begin;
506         if (type < attr_type_int64_begin)
507                 return attr_type_callback_begin;
508         if (type <= attr_type_int64_end)
509                 return attr_type_int64_begin;
510         return attr_none;
511 }
512
513 int
514 attr_data_size(struct attr *attr)
515 {
516         if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) 
517                 return strlen(attr->u.str)+1;
518         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) 
519                 return sizeof(attr->u.num);
520         if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) 
521                 return sizeof(*attr->u.coord_geo);
522         if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) 
523                 return sizeof(*attr->u.color);
524         if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) 
525                 return sizeof(void *);
526         if (attr->type >= attr_type_item_begin && attr->type <= attr_type_item_end) 
527                 return sizeof(struct item);
528         if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end) 
529                 return sizeof(*attr->u.num64);
530         if (attr->type == attr_order)
531                 return sizeof(attr->u.range);
532         if (attr->type >= attr_type_double_begin && attr->type <= attr_type_double_end) 
533                 return sizeof(*attr->u.numd);
534         if (attr->type == attr_item_types) {
535                 int i=0;
536                 while (attr->u.item_types[i++] != type_none);
537                 return i*sizeof(enum item_type);
538         }
539         if (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end)
540                 return sizeof(enum item_type);
541         if (attr->type == attr_attr_types) {
542                 int i=0;
543                 while (attr->u.attr_types[i++] != attr_none);
544                 return i*sizeof(enum attr_type);
545         }
546         dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
547         return 0;
548 }
549
550 void *
551 attr_data_get(struct attr *attr)
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                 return &attr->u.num;
556         if (attr->type == attr_order)
557                 return &attr->u.range;
558         return attr->u.data;
559 }
560
561 void
562 attr_data_set(struct attr *attr, void *data)
563 {
564         if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || 
565             (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end))
566                 attr->u.num=*((int *)data);
567         else
568                 attr->u.data=data;
569 }
570
571 void
572 attr_data_set_le(struct attr * attr, void * data)
573 {
574         if ((attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) || 
575             (attr->type >= attr_type_item_type_begin && attr->type <= attr_type_item_type_end))
576                 attr->u.num=le32_to_cpu(*((int *)data));
577         else if (attr->type == attr_order) {
578                 attr->u.num=le32_to_cpu(*((int *)data));
579                 attr->u.range.min=le16_to_cpu(attr->u.range.min);
580                 attr->u.range.max=le16_to_cpu(attr->u.range.max);
581         }
582         else
583 /* Fixme: Handle long long */
584                 attr->u.data=data;
585
586 }
587
588 void
589 attr_free(struct attr *attr)
590 {
591         if (!attr)
592                 return;
593         if (HAS_OBJECT_FUNC(attr->type)) {
594                 struct navit_object *obj=attr->u.data;
595                 if (obj && obj->func && obj->func->unref)
596                         obj->func->unref(obj);
597         }
598         if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) && 
599             !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end))
600                 g_free(attr->u.data);
601         g_free(attr);
602 }
603
604 void
605 attr_dup_content(struct attr *src, struct attr *dst)
606 {
607         int size;
608         dst->type=src->type;
609         if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end) 
610                 dst->u.num=src->u.num;
611         else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) {
612                 if (HAS_OBJECT_FUNC(src->type)) {
613                         struct navit_object *obj=src->u.data;
614                         if (obj && obj->func && obj->func->ref) {
615                                 dst->u.data=obj->func->ref(obj);
616                         } else
617                                 dst->u.data=obj;
618                 } else 
619                         dst->u.data=src->u.data;
620         } else {
621                 size=attr_data_size(src);
622                 if (size) {
623                         dst->u.data=g_malloc(size);
624                         memcpy(dst->u.data, src->u.data, size);
625                 }
626         }
627 }
628
629 struct attr *
630 attr_dup(struct attr *attr)
631 {
632         struct attr *ret=g_new0(struct attr, 1);
633         attr_dup_content(attr, ret);
634         return ret;
635 }
636
637 void
638 attr_list_free(struct attr **attrs)
639 {
640         int count=0;
641         while (attrs && attrs[count]) {
642                 attr_free(attrs[count++]);
643         }
644         g_free(attrs);
645 }
646
647 struct attr **
648 attr_list_dup(struct attr **attrs)
649 {
650         struct attr **ret;
651         int i,count=0;
652
653         if (!attrs)
654                 return NULL;
655
656         while (attrs[count])
657                 count++;
658         ret=g_new0(struct attr *, count+1);
659         for (i = 0 ; i < count ; i++)
660                 ret[i]=attr_dup(attrs[i]);
661         return ret;
662 }
663
664
665 int
666 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
667 {
668         int len=0,quoted;
669         char *p,*e,*n;
670
671         dbg(1,"get_tag %s from %s\n", name, line); 
672         if (name)
673                 len=strlen(name);
674         if (pos) 
675                 p=line+*pos;
676         else
677                 p=line;
678         for(;;) {
679                 while (*p == ' ') {
680                         p++;
681                 }
682                 if (! *p)
683                         return 0;
684                 n=p;
685                 e=strchr(p,'=');
686                 if (! e)
687                         return 0;
688                 p=e+1;
689                 quoted=0;
690                 while (*p) {
691                         if (*p == ' ' && !quoted)
692                                 break;
693                         if (*p == '"')
694                                 quoted=1-quoted;
695                         p++;
696                 }
697                 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
698                         if (name_ret) {
699                                 len=e-n;
700                                 strncpy(name_ret, n, len);
701                                 name_ret[len]='\0';
702                         }
703                         e++;
704                         len=p-e;
705                         if (e[0] == '"') {
706                                 e++;
707                                 len-=2;
708                         }
709                         strncpy(val_ret, e, len);
710                         val_ret[len]='\0';
711                         if (pos)
712                                 *pos=p-line;
713                         return 1;
714                 }
715         }       
716         return 0;
717 }
718
719 /**
720  * Check if an enumeration of attribute types contains a specific attribute.
721  *
722  * @param types Pointer to the attr_type enumeration to be searched
723  * @param type The attr_type to be searched for
724  *
725  * @return 1 if the attribute type was found, 0 if it was not found or if a null pointer was passed as types
726  */
727 int
728 attr_types_contains(enum attr_type *types, enum attr_type type)
729 {
730         while (types && *types != attr_none) {
731                 if (*types == type)
732                         return 1;
733                 types++;
734         }
735         return 0;
736 }
737
738 /**
739  * Check if an enumeration of attribute types contains a specific attribute. 
740  * It is different from attr_types_contains in that it returns a caller-defined value if the pointer to the enumeration is NULL.
741  *
742  * @param types Pointer to the attr_type enumeration to be searched
743  * @param type The attr_type to be searched for
744  * @param deflt The default value to return if types is NULL.
745  *
746  * @return 1 if the attribute type was found, 0 if it was not found, the value of the deflt argument if types is NULL.
747  */
748 int
749 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
750 {
751         if (!types) {
752                 return deflt;
753         }
754         return attr_types_contains(types, type);        
755 }