/[zanavi_public1]/navit/navit/attr.c
ZANavi

Contents of /navit/navit/attr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki