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