uninitialized variables checked. Also change two if/else if functions for switch
[lttv.git] / ltt / branches / poly / lttv / lttv / attribute.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #include <lttv/attribute.h>
20 #include <ltt/ltt.h>
21
22 typedef union _AttributeValue {
23 int dv_int;
24 unsigned dv_uint;
25 long dv_long;
26 unsigned long dv_ulong;
27 float dv_float;
28 double dv_double;
29 LttTime dv_time;
30 gpointer dv_pointer;
31 char *dv_string;
32 GObject *dv_gobject;
33 } AttributeValue;
34
35
36 typedef struct _Attribute {
37 LttvAttributeName name;
38 LttvAttributeType type;
39 AttributeValue value;
40 } Attribute;
41
42
43 LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
44 {
45 LttvAttributeValue va;
46
47 switch(t) {
48 case LTTV_INT: va.v_int = &v->dv_int; break;
49 case LTTV_UINT: va.v_uint = &v->dv_uint; break;
50 case LTTV_LONG: va.v_long = &v->dv_long; break;
51 case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break;
52 case LTTV_FLOAT: va.v_float = &v->dv_float; break;
53 case LTTV_DOUBLE: va.v_double = &v->dv_double; break;
54 case LTTV_TIME: va.v_time = &v->dv_time; break;
55 case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break;
56 case LTTV_STRING: va.v_string = &v->dv_string; break;
57 case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break;
58 }
59 return va;
60 }
61
62
63 AttributeValue init_value(LttvAttributeType t)
64 {
65 AttributeValue v;
66
67 switch(t) {
68 case LTTV_INT: v.dv_int = 0; break;
69 case LTTV_UINT: v.dv_uint = 0; break;
70 case LTTV_LONG: v.dv_long = 0; break;
71 case LTTV_ULONG: v.dv_ulong = 0; break;
72 case LTTV_FLOAT: v.dv_float = 0; break;
73 case LTTV_DOUBLE: v.dv_double = 0; break;
74 case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break;
75 case LTTV_POINTER: v.dv_pointer = NULL; break;
76 case LTTV_STRING: v.dv_string = NULL; break;
77 case LTTV_GOBJECT: v.dv_gobject = NULL; break;
78 }
79 return v;
80 }
81
82
83 unsigned int
84 lttv_attribute_get_number(LttvAttribute *self)
85 {
86 return self->attributes->len;
87 }
88
89
90 gboolean
91 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
92 {
93 *homogeneous = FALSE;
94 return TRUE;
95 }
96
97
98 LttvAttributeType
99 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
100 LttvAttributeValue *v)
101 {
102 Attribute *a;
103
104 a = &g_array_index(self->attributes, Attribute, i);
105 *name = a->name;
106 *v = address_of_value(a->type, &(a->value));
107 return a->type;
108 }
109
110
111 LttvAttributeType
112 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
113 LttvAttributeValue *v)
114 {
115 Attribute *a;
116
117 unsigned i;
118
119 gpointer p;
120
121 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
122 if(p == NULL) return LTTV_NONE;
123
124 i = GPOINTER_TO_UINT(p);
125 i--;
126 a = &g_array_index(self->attributes, Attribute, i);
127 *v = address_of_value(a->type, &(a->value));
128 return a->type;
129 }
130
131
132 LttvAttributeValue
133 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
134 LttvAttributeType t)
135 {
136 unsigned i;
137
138 Attribute a, *pa;
139
140 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
141 if(i != 0) g_error("duplicate entry in attribute table");
142
143 a.name = name;
144 a.type = t;
145 a.value = init_value(t);
146 g_array_append_val(self->attributes, a);
147 i = self->attributes->len - 1;
148 pa = &g_array_index(self->attributes, Attribute, i);
149 g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
150 GUINT_TO_POINTER(i + 1));
151 return address_of_value(t, &(pa->value));
152 }
153
154
155 /* Remove an attribute */
156
157 void
158 lttv_attribute_remove(LttvAttribute *self, unsigned i)
159 {
160 Attribute *a;
161
162 a = &g_array_index(self->attributes, Attribute, i);
163
164 /* If the element is a gobject, unreference it. */
165 if(a->type == LTTV_GOBJECT && a->value.dv_gobject != NULL)
166 g_object_unref(a->value.dv_gobject);
167
168 /* Remove the array element and its entry in the name index */
169
170 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
171 g_array_remove_index_fast(self->attributes, i);
172
173 /* The element used to replace the removed element has its index entry
174 all wrong now. Reinsert it with its new position. */
175
176 if(self->attributes->len != i){
177 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
178 g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
179 }
180 }
181
182 void
183 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
184 {
185 unsigned i;
186
187 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
188 if(i == 0) g_error("remove by name non existent attribute");
189
190 lttv_attribute_remove(self, i - 1);
191 }
192
193 /* Create an empty iattribute object and add it as an attribute under the
194 specified name, or return an existing iattribute attribute. If an
195 attribute of that name already exists but is not a GObject supporting the
196 iattribute interface, return NULL. */
197
198 /*CHECK*/LttvAttribute*
199 lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
200 {
201 unsigned i;
202
203 Attribute a;
204
205 LttvAttribute *new;
206
207 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
208 if(i != 0) {
209 a = g_array_index(self->attributes, Attribute, i - 1);
210 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
211 return LTTV_ATTRIBUTE(a.value.dv_gobject);
212 }
213 else return NULL;
214 }
215 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
216 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
217 return (LttvAttribute *)new;
218 }
219
220 gboolean
221 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
222 LttvAttributeType t, LttvAttributeValue *v)
223 {
224 unsigned i;
225
226 Attribute *a;
227
228 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
229 if(i != 0) {
230 a = &g_array_index(self->attributes, Attribute, i - 1);
231 if(a->type != t) return FALSE;
232 *v = address_of_value(t, &(a->value));
233 return TRUE;
234 }
235
236 *v = lttv_attribute_add(self, name, t);
237 return TRUE;
238 }
239
240
241 /*void lttv_attribute_recursive_free(LttvAttribute *self)
242 {
243 int i, nb;
244
245 Attribute *a;
246
247 nb = self->attributes->len;
248
249 for(i = 0 ; i < nb ; i++) {
250 a = &g_array_index(self->attributes, Attribute, i);
251 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
252 lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
253 }
254 }
255 g_object_unref(self);
256 }*/
257
258
259 void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
260 {
261 int i, nb;
262
263 Attribute *a;
264
265 LttvAttributeValue value;
266
267 nb = src->attributes->len;
268
269 for(i = 0 ; i < nb ; i++) {
270 a = &g_array_index(src->attributes, Attribute, i);
271 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
272 lttv_attribute_recursive_add(
273 /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
274 (LttvAttribute *)(a->value.dv_gobject));
275 }
276 else {
277 g_assert(lttv_attribute_find(dest, a->name, a->type, &value));
278 switch(a->type) {
279 case LTTV_INT:
280 *value.v_int += a->value.dv_int;
281 break;
282 case LTTV_UINT:
283 *value.v_uint += a->value.dv_uint;
284 break;
285 case LTTV_LONG:
286 *value.v_long += a->value.dv_long;
287 break;
288 case LTTV_ULONG:
289 *value.v_ulong += a->value.dv_ulong;
290 break;
291 case LTTV_FLOAT:
292 *value.v_float += a->value.dv_float;
293 break;
294 case LTTV_DOUBLE:
295 *value.v_double += a->value.dv_double;
296 break;
297 case LTTV_TIME:
298 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
299 break;
300 case LTTV_POINTER:
301 break;
302 case LTTV_STRING:
303 break;
304 case LTTV_GOBJECT:
305 break;
306 case LTTV_NONE:
307 break;
308 }
309 }
310 }
311 }
312
313
314 static void
315 print_indent(FILE *fp, int pos)
316 {
317 int i;
318
319 for(i = 0 ; i < pos ; i++) putc(' ', fp);
320 }
321
322
323 void
324 lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent)
325 {
326 int i, nb;
327
328 Attribute *a;
329
330 nb = self->attributes->len;
331
332 fprintf(fp,"<ATTRS>\n");
333 for(i = 0 ; i < nb ; i++) {
334 a = &g_array_index(self->attributes, Attribute, i);
335 print_indent(fp, pos);
336 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
337 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
338 fprintf(fp, "TYPE=ATTRS>");
339 lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp,
340 pos + indent, indent);
341 }
342 else {
343 switch(a->type) {
344 case LTTV_INT:
345 fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int);
346 break;
347 case LTTV_UINT:
348 fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint);
349 break;
350 case LTTV_LONG:
351 fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long);
352 break;
353 case LTTV_ULONG:
354 fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong);
355 break;
356 case LTTV_FLOAT:
357 fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float);
358 break;
359 case LTTV_DOUBLE:
360 fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double);
361 break;
362 case LTTV_TIME:
363 fprintf(fp, "TYPE=TIME SEC=%u NSEC=%u/>\n", a->value.dv_time.tv_sec,
364 a->value.dv_time.tv_nsec);
365 break;
366 case LTTV_POINTER:
367 fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer);
368 break;
369 case LTTV_STRING:
370 fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string);
371 break;
372 case LTTV_GOBJECT:
373 fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject);
374 break;
375 case LTTV_NONE:
376 fprintf(fp, "TYPE=NONE/>\n");
377 break;
378 }
379 }
380 }
381 print_indent(fp, pos);
382 fprintf(fp,"</ATTRS>\n");
383 }
384
385
386 void
387 lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
388 {
389 int i, nb, res;
390
391 Attribute *a;
392
393 char buffer[256], type[10];
394
395 LttvAttributeName name;
396
397 LttvAttributeValue value;
398
399 LttvAttribute *subtree;
400
401 fscanf(fp,"<ATTRS>");
402 while(1) {
403 res = fscanf(fp, "<ATTR NAME=\"%256[^\"]\" TYPE=%10[^ >]", buffer, type);
404 g_assert(res == 2);
405 name = g_quark_from_string(buffer);
406 if(strcmp(type, "ATTRS") == 0) {
407 fscanf(fp, ">");
408 subtree = lttv_attribute_find_subdir(self, name);
409 lttv_attribute_read_xml(subtree, fp);
410 }
411 else if(strcmp(type, "INT") == 0) {
412 value = lttv_attribute_add(self, name, LTTV_INT);
413 res = fscanf(fp, " VALUE=%d/>", value.v_int);
414 g_assert(res == 1);
415 }
416 else if(strcmp(type, "UINT") == 0) {
417 value = lttv_attribute_add(self, name, LTTV_UINT);
418 res = fscanf(fp, " VALUE=%u/>", value.v_uint);
419 g_assert(res == 1);
420 }
421 else if(strcmp(type, "LONG") == 0) {
422 value = lttv_attribute_add(self, name, LTTV_LONG);
423 res = fscanf(fp, " VALUE=%ld/>", value.v_long);
424 g_assert(res == 1);
425 }
426 else if(strcmp(type, "ULONG") == 0) {
427 value = lttv_attribute_add(self, name, LTTV_ULONG);
428 res = fscanf(fp, " VALUE=%lu/>", value.v_ulong);
429 g_assert(res == 1);
430 }
431 else if(strcmp(type, "FLOAT") == 0) {
432 float d;
433 value = lttv_attribute_add(self, name, LTTV_FLOAT);
434 res = fscanf(fp, " VALUE=%f/>", &d);
435 *(value.v_float) = d;
436 g_assert(res == 1);
437 }
438 else if(strcmp(type, "DOUBLE") == 0) {
439 value = lttv_attribute_add(self, name, LTTV_DOUBLE);
440 res = fscanf(fp, " VALUE=%f/>", value.v_double);
441 g_assert(res == 1);
442 }
443 else if(strcmp(type, "TIME") == 0) {
444 value = lttv_attribute_add(self, name, LTTV_TIME);
445 res = fscanf(fp, " SEC=%u NSEC=%u/>", &(value.v_time->tv_sec),
446 &(value.v_time->tv_nsec));
447 g_assert(res == 2);
448 }
449 else if(strcmp(type, "POINTER") == 0) {
450 value = lttv_attribute_add(self, name, LTTV_POINTER);
451 res = fscanf(fp, " VALUE=%p/>", value.v_pointer);
452 g_error("Cannot read a pointer");
453 }
454 else if(strcmp(type, "STRING") == 0) {
455 value = lttv_attribute_add(self, name, LTTV_STRING);
456 res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer);
457 *(value.v_string) = g_strdup(buffer);
458 g_assert(res == 1);
459 }
460 else if(strcmp(type, "GOBJECT") == 0) {
461 value = lttv_attribute_add(self, name, LTTV_GOBJECT);
462 res = fscanf(fp, " VALUE=%p/>", value.v_gobject);
463 g_error("Cannot read a pointer");
464 }
465 else if(strcmp(type, "NONE") == 0) {
466 value = lttv_attribute_add(self, name, LTTV_NONE);
467 fscanf(fp, "/>");
468 }
469 else g_error("Unknown type to read");
470 }
471 fscanf(fp,"</ATTRS>");
472 }
473
474 static LttvAttribute *
475 new_attribute (LttvAttribute *self)
476 {
477 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
478 }
479
480
481 static void
482 attribute_interface_init (gpointer g_iface, gpointer iface_data)
483 {
484 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
485
486 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
487 new_attribute;
488
489 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
490 lttv_attribute_get_number;
491
492 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
493 lttv_attribute_named;
494
495 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
496 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
497
498 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
499 LttvAttributeName name, LttvAttributeValue *v))
500 lttv_attribute_get_by_name;
501
502 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
503 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
504
505 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
506 lttv_attribute_remove;
507
508 klass->remove_by_name = (void (*) (LttvIAttribute *self,
509 LttvAttributeName name)) lttv_attribute_remove_by_name;
510
511 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
512 LttvAttributeName name)) lttv_attribute_find_subdir;
513
514 }
515
516
517 static void
518 attribute_instance_init (GTypeInstance *instance, gpointer g_class)
519 {
520 LttvAttribute *self = (LttvAttribute *)instance;
521 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
522 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
523 }
524
525
526 static void
527 attribute_finalize (LttvAttribute *self)
528 {
529 guint i;
530 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
531
532 for(i=0;i<self->attributes->len;i++) {
533 lttv_attribute_remove(self, i);
534 }
535
536 g_hash_table_destroy(self->names);
537 g_array_free(self->attributes, TRUE);
538 }
539
540
541 static void
542 attribute_class_init (LttvAttributeClass *klass)
543 {
544 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
545
546 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
547 }
548
549 GType
550 lttv_attribute_get_type (void)
551 {
552 static GType type = 0;
553 if (type == 0) {
554 static const GTypeInfo info = {
555 sizeof (LttvAttributeClass),
556 NULL, /* base_init */
557 NULL, /* base_finalize */
558 (GClassInitFunc) attribute_class_init, /* class_init */
559 NULL, /* class_finalize */
560 NULL, /* class_data */
561 sizeof (LttvAttribute),
562 0, /* n_preallocs */
563 (GInstanceInitFunc) attribute_instance_init /* instance_init */
564 };
565
566 static const GInterfaceInfo iattribute_info = {
567 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
568 NULL, /* interface_finalize */
569 NULL /* interface_data */
570 };
571
572 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
573 0);
574 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
575 }
576 return type;
577 }
578
579
This page took 0.041055 seconds and 5 git commands to generate.