Fix:maptool:Another name for faroe islands
[navit-package] / 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
34 struct attr_name {
35         enum attr_type attr;
36         char *name;
37 };
38
39
40 static struct attr_name attr_names[]={
41 #define ATTR2(x,y) ATTR(y)
42 #define ATTR(x) { attr_##x, #x },
43 #include "attr_def.h"
44 #undef ATTR2
45 #undef ATTR
46 };
47
48 enum attr_type
49 attr_from_name(const char *name)
50 {
51         int i;
52
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;
56         }
57         return attr_none;
58 }
59
60
61 static int attr_match(enum attr_type search, enum attr_type found);
62
63
64
65 char *
66 attr_to_name(enum attr_type attr)
67 {
68         int i;
69
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;
73         }
74         return NULL; 
75 }
76
77 struct attr *
78 attr_new_from_text(const char *name, const char *value)
79 {
80         enum attr_type attr;
81         struct attr *ret;
82         struct coord_geo *g;
83         struct coord c;
84         char *pos,*type_str,*str,*tok;
85         int min,max,count;
86
87         ret=g_new0(struct attr, 1);
88         dbg(1,"enter name='%s' value='%s'\n", name, value);
89         attr=attr_from_name(name);
90         ret->type=attr;
91         switch (attr) {
92         case attr_item_type:
93                 ret->u.item_type=item_from_name(value);
94                 break;
95         case attr_item_types:
96                 count=0;
97                 type_str=g_strdup(value);
98                 str=type_str;
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;
103                         str=NULL;
104                 }
105                 g_free(type_str);
106                 break;
107         case attr_attr_types:
108                 count=0;
109                 type_str=g_strdup(value);
110                 str=type_str;
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;
115                         str=NULL;
116                 }
117                 g_free(type_str);
118                 break;
119         case attr_dash:
120                 count=0;
121                 type_str=g_strdup(value);
122                 str=type_str;
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;
127                         str=NULL;
128                 }
129                 g_free(type_str);
130                 break;
131         case attr_order:
132         case attr_sequence_range:
133         case attr_angle_range:
134         case attr_speed_range:
135                 pos=strchr(value, '-');
136                 min=0;
137                 max=32767;
138                 if (! pos) {
139                         sscanf(value,"%d",&min);
140                         max=min;
141                 } else if (pos == value)
142                         sscanf(value,"-%d",&max);
143                 else
144                         sscanf(value,"%d-%d",&min, &max);
145                 ret->u.range.min=min;
146                 ret->u.range.max=max;
147                 break;
148         default:
149                 if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
150                         ret->u.str=g_strdup(value);
151                         break;
152                 }
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);
156                         else
157                                 ret->u.num=strtol(value, NULL, 0);
158                         
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);
165                                         }
166
167                                         ret->u.num += 0x60000000;
168                                 } else {
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);
171                                         }
172                                 }
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")) 
175                                         ret->u.num=1;
176                                 else
177                                         ret->u.num=0;
178                         }
179                         break;
180                 }
181                 if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
182                         struct color *color=g_new0(struct color, 1);
183                         int r,g,b,a;
184                         ret->u.color=color;
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;
190                                 color->a = (65535);
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;
197                         } else {
198                                 dbg(0,"color %s has unknown format\n",value);
199                         }
200                         break;
201                 }
202                 if (attr >= attr_type_coord_geo_begin && attr <= attr_type_coord_geo_end) {
203                         g=g_new(struct coord_geo, 1);
204                         ret->u.coord_geo=g;
205                         coord_parse(value, projection_mg, &c);
206                         transform_to_geo(projection_mg, &c, g);
207                         break;
208                 }
209                 dbg(1,"default\n");
210                 g_free(ret);
211                 ret=NULL;
212         }
213         return ret;
214 }
215
216 char *
217 attr_to_text(struct attr *attr, struct map *map, int pretty)
218 {
219         char *ret;
220         enum attr_type type=attr->type;
221
222         if (type >= attr_type_item_begin && type <= attr_type_item_end) {
223                 struct item *item=attr->u.item;
224                 struct attr type, data;
225                 if (! item)
226                         return g_strdup("(nil)");
227                 if (! item->map || !map_get_attr(item->map, attr_type, &type, NULL))
228                         type.u.str="";
229                 if (! item->map || !map_get_attr(item->map, attr_data, &data, NULL))
230                         data.u.str="";
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);
232         }
233         if (type >= attr_type_string_begin && type <= attr_type_string_end) {
234                 if (map) {
235                         char *mstr;
236                         if (attr->u.str) {
237                                 mstr=map_convert_string(map, attr->u.str);
238                                 ret=g_strdup(mstr);
239                                 map_convert_free(mstr);
240                         } else
241                                 ret=g_strdup("(null)");
242                         
243                 } else
244                         ret=g_strdup(attr->u.str);
245                 return ret;
246         }
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);
260                 else
261                         return g_strdup_printf("#%02x%02x%02x", attr->u.color->r>>8,attr->u.color->g>>8,attr->u.color->b>>8);
262         }
263         if (type >= attr_type_coord_geo_begin && type <= attr_type_coord_geo_end) 
264                 return g_strdup_printf("%f %f",attr->u.coord_geo->lng,attr->u.coord_geo->lat);
265         if (type == attr_zipfile_ref_block) {
266                 int *data=attr->u.data;
267                 return g_strdup_printf("0x%x,0x%x,0x%x",data[0],data[1],data[2]);
268         }
269         return g_strdup_printf("(no text[%s])", attr_to_name(type));    
270 }
271
272 struct attr *
273 attr_search(struct attr **attrs, struct attr *last, enum attr_type attr)
274 {
275         dbg(1, "enter attrs=%p\n", attrs);
276         while (*attrs) {
277                 dbg(1,"*attrs=%p\n", *attrs);
278                 if ((*attrs)->type == attr) {
279                         return *attrs;
280                 }
281                 attrs++;
282         }
283         return NULL;
284 }
285
286 static int
287 attr_match(enum attr_type search, enum attr_type found)
288 {
289         switch (search) {
290         case attr_any:
291                 return 1;
292         case attr_any_xml:
293                 switch (found) {
294                 case attr_callback:
295                         return 0;
296                 default:
297                         return 1;
298                 }
299         default:
300                 return search == found;
301         }
302 }
303
304 int
305 attr_generic_get_attr(struct attr **attrs, struct attr **def_attrs, enum attr_type type, struct attr *attr, struct attr_iter *iter)
306 {
307         while (attrs && *attrs) {
308                 if (attr_match(type,(*attrs)->type)) {
309                         *attr=**attrs;
310                         if (!iter)
311                                 return 1;
312                         if (*((void **)iter) < (void *)attrs) {
313                                 *((void **)iter)=(void *)attrs;
314                                 return 1;
315                         }
316                 }
317                 attrs++;
318         }
319         if (type == attr_any || type == attr_any_xml)
320                 return 0;
321         while (def_attrs && *def_attrs) {
322                 if ((*def_attrs)->type == type) {
323                         *attr=**def_attrs;
324                         return 1;
325                 }
326                 def_attrs++;
327         }
328         return 0;
329 }
330
331 struct attr **
332 attr_generic_set_attr(struct attr **attrs, struct attr *attr)
333 {
334         struct attr **curr=attrs;
335         int i,count=0;
336         while (curr && *curr) {
337                 if ((*curr)->type == attr->type) {
338                         attr_free(*curr);
339                         *curr=attr_dup(attr);
340                         return attrs;
341                 }
342                 curr++;
343                 count++;
344         }
345         curr=g_new0(struct attr *, count+2);
346         for (i = 0 ; i < count ; i++)
347                 curr[i]=attrs[i];
348         curr[count]=attr_dup(attr);
349         curr[count+1]=NULL;
350         g_free(attrs);
351         return curr;
352 }
353
354 struct attr **
355 attr_generic_add_attr(struct attr **attrs, struct attr *attr)
356 {
357         struct attr **curr=attrs;
358         int i,count=0;
359         while (curr && *curr) {
360                 curr++;
361                 count++;
362         }
363         curr=g_new0(struct attr *, count+2);
364         for (i = 0 ; i < count ; i++)
365                 curr[i]=attrs[i];
366         curr[count]=attr_dup(attr);
367         curr[count+1]=NULL;
368         g_free(attrs);
369         return curr;
370 }
371
372 struct attr **
373 attr_generic_remove_attr(struct attr **attrs, struct attr *attr)
374 {
375         struct attr **curr=attrs;
376         int i,j,count=0,found=0;
377         while (curr && *curr) {
378                 if ((*curr)->type == attr->type && (*curr)->u.data == attr->u.data)
379                         found=1;
380                 curr++;
381                 count++;
382         }
383         if (!found)
384                 return attrs;
385         curr=g_new0(struct attr *, count);
386         j=0;
387         for (i = 0 ; i < count ; i++) {
388                 if (attrs[i]->type != attr->type || attrs[i]->u.data != attr->u.data)
389                         curr[j++]=attrs[i];
390                 else
391                         attr_free(attrs[i]);
392         }
393         curr[j]=NULL;
394         g_free(attrs);
395         return curr;
396 }
397
398 enum attr_type
399 attr_type_begin(enum attr_type type)
400 {
401         if (type < attr_type_item_begin)
402                 return attr_none;
403         if (type < attr_type_int_begin)
404                 return attr_type_item_begin;
405         if (type < attr_type_string_begin)
406                 return attr_type_int_begin;
407         if (type < attr_type_special_begin)
408                 return attr_type_string_begin;
409         if (type < attr_type_double_begin)
410                 return attr_type_special_begin;
411         if (type < attr_type_coord_geo_begin)
412                 return attr_type_double_begin;
413         if (type < attr_type_color_begin)
414                 return attr_type_coord_geo_begin;
415         if (type < attr_type_object_begin)
416                 return attr_type_color_begin;
417         if (type < attr_type_coord_begin)
418                 return attr_type_object_begin;
419         if (type < attr_type_pcoord_begin)
420                 return attr_type_coord_begin;
421         if (type < attr_type_callback_begin)
422                 return attr_type_pcoord_begin;
423         if (type < attr_type_int64_begin)
424                 return attr_type_callback_begin;
425         if (type <= attr_type_int64_end)
426                 return attr_type_int64_begin;
427         return attr_none;
428 }
429
430 int
431 attr_data_size(struct attr *attr)
432 {
433         if (attr->type >= attr_type_string_begin && attr->type <= attr_type_string_end) 
434                 return strlen(attr->u.str)+1;
435         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) 
436                 return sizeof(attr->u.num);
437         if (attr->type >= attr_type_coord_geo_begin && attr->type <= attr_type_coord_geo_end) 
438                 return sizeof(*attr->u.coord_geo);
439         if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) 
440                 return sizeof(*attr->u.color);
441         if (attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end) 
442                 return sizeof(void *);
443         if (attr->type >= attr_type_int64_begin && attr->type <= attr_type_int64_end) 
444                 return sizeof(*attr->u.num64);
445         if (attr->type == attr_order)
446                 return sizeof(attr->u.range);
447         if (attr->type == attr_item_types) {
448                 int i=0;
449                 while (attr->u.item_types[i++] != type_none);
450                 return i*sizeof(enum item_type);
451         }
452         if (attr->type == attr_attr_types) {
453                 int i=0;
454                 while (attr->u.attr_types[i++] != attr_none);
455                 return i*sizeof(enum attr_type);
456         }
457         dbg(0,"size for %s unknown\n", attr_to_name(attr->type));
458         return 0;
459 }
460
461 void *
462 attr_data_get(struct attr *attr)
463 {
464         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) 
465                 return &attr->u.num;
466         if (attr->type == attr_order)
467                 return &attr->u.range;
468         return attr->u.data;
469 }
470
471 void
472 attr_data_set(struct attr *attr, void *data)
473 {
474         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) 
475                 attr->u.num=*((int *)data);
476         else
477                 attr->u.data=data;
478 }
479
480 void
481 attr_data_set_le(struct attr * attr, void * data)
482 {
483         if (attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) 
484                 attr->u.num=le32_to_cpu(*((int *)data));
485         else if (attr->type == attr_order) {
486                 attr->u.num=le32_to_cpu(*((int *)data));
487                 attr->u.range.min=le16_to_cpu(attr->u.range.min);
488                 attr->u.range.max=le16_to_cpu(attr->u.range.max);
489         }
490         else
491 /* Fixme: Handle long long */
492                 attr->u.data=data;
493
494 }
495
496 void
497 attr_free(struct attr *attr)
498 {
499         if (!attr)
500                 return;
501         if (!(attr->type >= attr_type_int_begin && attr->type <= attr_type_int_end) && 
502             !(attr->type >= attr_type_object_begin && attr->type <= attr_type_object_end))
503                 g_free(attr->u.data);
504         g_free(attr);
505 }
506
507 void
508 attr_dup_content(struct attr *src, struct attr *dst)
509 {
510         int size;
511         dst->type=src->type;
512         if (src->type >= attr_type_int_begin && src->type <= attr_type_int_end) 
513                 dst->u.num=src->u.num;
514         else if (src->type >= attr_type_object_begin && src->type <= attr_type_object_end) 
515                 dst->u.data=src->u.data;
516         else {
517                 size=attr_data_size(src);
518                 if (size) {
519                         dst->u.data=g_malloc(size);
520                         memcpy(dst->u.data, src->u.data, size);
521                 }
522         }
523 }
524
525 struct attr *
526 attr_dup(struct attr *attr)
527 {
528         struct attr *ret=g_new0(struct attr, 1);
529         attr_dup_content(attr, ret);
530         return ret;
531 }
532
533 void
534 attr_list_free(struct attr **attrs)
535 {
536         int count=0;
537         while (attrs && attrs[count]) {
538                 attr_free(attrs[count++]);
539         }
540         g_free(attrs);
541 }
542
543 struct attr **
544 attr_list_dup(struct attr **attrs)
545 {
546         struct attr **ret=attrs;
547         int i,count=0;
548
549         while (attrs[count])
550                 count++;
551         ret=g_new0(struct attr *, count+1);
552         for (i = 0 ; i < count ; i++)
553                 ret[i]=attr_dup(attrs[i]);
554         return ret;
555 }
556
557
558 int
559 attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret)
560 {
561         int len=0,quoted;
562         char *p,*e,*n;
563
564         dbg(1,"get_tag %s from %s\n", name, line); 
565         if (name)
566                 len=strlen(name);
567         if (pos) 
568                 p=line+*pos;
569         else
570                 p=line;
571         for(;;) {
572                 while (*p == ' ') {
573                         p++;
574                 }
575                 if (! *p)
576                         return 0;
577                 n=p;
578                 e=strchr(p,'=');
579                 if (! e)
580                         return 0;
581                 p=e+1;
582                 quoted=0;
583                 while (*p) {
584                         if (*p == ' ' && !quoted)
585                                 break;
586                         if (*p == '"')
587                                 quoted=1-quoted;
588                         p++;
589                 }
590                 if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
591                         if (name_ret) {
592                                 len=e-n;
593                                 strncpy(name_ret, n, len);
594                                 name_ret[len]='\0';
595                         }
596                         e++;
597                         len=p-e;
598                         if (e[0] == '"') {
599                                 e++;
600                                 len-=2;
601                         }
602                         strncpy(val_ret, e, len);
603                         val_ret[len]='\0';
604                         if (pos)
605                                 *pos=p-line;
606                         return 1;
607                 }
608         }       
609         return 0;
610 }
611
612 int
613 attr_types_contains(enum attr_type *types, enum attr_type type)
614 {
615         while (types && *types != attr_none) {
616                 if (*types == type)
617                         return 1;
618                 types++;
619         }
620         return 0;
621 }
622
623 int
624 attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt)
625 {
626         if (!types) {
627                 return deflt;
628         }
629         return attr_types_contains(types, type);        
630 }