uninitialized variables checked, plus O2 optimisations checked : strict aliasing...
[lttv.git] / ltt / branches / poly / lttv / lttv / attribute.c
CommitLineData
9c312311 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 */
dc877563 18
00e74b69 19#include <string.h>
fcdf0ec2 20#include <lttv/attribute.h>
b445142a 21#include <ltt/ltt.h>
f32847a1 22
dc877563 23typedef 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;
308711e5 30 LttTime dv_time;
dc877563 31 gpointer dv_pointer;
32 char *dv_string;
ffd54a90 33 GObject *dv_gobject;
dc877563 34} AttributeValue;
35
36
37typedef struct _Attribute {
38 LttvAttributeName name;
39 LttvAttributeType type;
40 AttributeValue value;
41} Attribute;
42
43
ffd54a90 44LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
dc877563 45{
ffd54a90 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;
00e74b69 59 case LTTV_NONE: break;
ffd54a90 60 }
61 return va;
62}
dc877563 63
dc877563 64
ffd54a90 65AttributeValue 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;
00e74b69 80 case LTTV_NONE: break;
dc877563 81 }
ffd54a90 82 return v;
f32847a1 83}
84
85
dc877563 86unsigned int
87lttv_attribute_get_number(LttvAttribute *self)
88{
89 return self->attributes->len;
f32847a1 90}
91
92
dc877563 93gboolean
94lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
95{
96 *homogeneous = FALSE;
97 return TRUE;
f32847a1 98}
99
100
dc877563 101LttvAttributeType
102lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
103 LttvAttributeValue *v)
104{
105 Attribute *a;
f32847a1 106
dc877563 107 a = &g_array_index(self->attributes, Attribute, i);
108 *name = a->name;
ffd54a90 109 *v = address_of_value(a->type, &(a->value));
dc877563 110 return a->type;
f32847a1 111}
112
113
dc877563 114LttvAttributeType
115lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
116 LttvAttributeValue *v)
117{
118 Attribute *a;
f32847a1 119
dc877563 120 unsigned i;
f32847a1 121
ffd54a90 122 gpointer p;
123
124 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
125 if(p == NULL) return LTTV_NONE;
f32847a1 126
ba576a78 127 i = GPOINTER_TO_UINT(p);
dc877563 128 i--;
129 a = &g_array_index(self->attributes, Attribute, i);
ffd54a90 130 *v = address_of_value(a->type, &(a->value));
dc877563 131 return a->type;
f32847a1 132}
133
f32847a1 134
dc877563 135LttvAttributeValue
136lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
137 LttvAttributeType t)
138{
139 unsigned i;
f32847a1 140
dc877563 141 Attribute a, *pa;
f32847a1 142
ffd54a90 143 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 144 if(i != 0) g_error("duplicate entry in attribute table");
f32847a1 145
ffd54a90 146 a.name = name;
147 a.type = t;
148 a.value = init_value(t);
dc877563 149 g_array_append_val(self->attributes, a);
150 i = self->attributes->len - 1;
ffd54a90 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));
f32847a1 155}
156
157
dc877563 158/* Remove an attribute */
f32847a1 159
dc877563 160void
161lttv_attribute_remove(LttvAttribute *self, unsigned i)
f32847a1 162{
dc877563 163 Attribute *a;
f32847a1 164
dc877563 165 a = &g_array_index(self->attributes, Attribute, i);
f32847a1 166
c47a6dc6 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
dc877563 171 /* Remove the array element and its entry in the name index */
f32847a1 172
ffd54a90 173 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
dc877563 174 g_array_remove_index_fast(self->attributes, i);
f32847a1 175
dc877563 176 /* The element used to replace the removed element has its index entry
177 all wrong now. Reinsert it with its new position. */
f32847a1 178
c6bc9cb9 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 }
f32847a1 183}
184
dc877563 185void
186lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
187{
188 unsigned i;
f32847a1 189
ffd54a90 190 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 191 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 192
dc877563 193 lttv_attribute_remove(self, i - 1);
f32847a1 194}
195
dc877563 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. */
f32847a1 200
b445142a 201/*CHECK*/LttvAttribute*
202lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 203{
dc877563 204 unsigned i;
f32847a1 205
dc877563 206 Attribute a;
f32847a1 207
dc877563 208 LttvAttribute *new;
a43d67ba 209
ffd54a90 210 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 211 if(i != 0) {
212 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 213 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
b445142a 214 return LTTV_ATTRIBUTE(a.value.dv_gobject);
dc877563 215 }
216 else return NULL;
f32847a1 217 }
ffd54a90 218 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
219 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
b445142a 220 return (LttvAttribute *)new;
f32847a1 221}
222
dc877563 223gboolean
224lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
225 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 226{
dc877563 227 unsigned i;
f32847a1 228
dc877563 229 Attribute *a;
f32847a1 230
ffd54a90 231 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 232 if(i != 0) {
233 a = &g_array_index(self->attributes, Attribute, i - 1);
234 if(a->type != t) return FALSE;
ffd54a90 235 *v = address_of_value(t, &(a->value));
dc877563 236 return TRUE;
237 }
f32847a1 238
dc877563 239 *v = lttv_attribute_add(self, name, t);
240 return TRUE;
f32847a1 241}
242
f32847a1 243
c47a6dc6 244/*void lttv_attribute_recursive_free(LttvAttribute *self)
b445142a 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);
c47a6dc6 259}*/
b445142a 260
261
262void 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) {
c47a6dc6 282 case LTTV_INT:
b445142a 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:
308711e5 301 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
b445142a 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
f95bc830 317static void
318print_indent(FILE *fp, int pos)
319{
320 int i;
321
322 for(i = 0 ; i < pos ; i++) putc(' ', fp);
323}
324
325
326void
327lttv_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);
5bf80c50 339 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
f95bc830 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:
00e74b69 366 fprintf(fp, "TYPE=TIME SEC=%lu NSEC=%lu/>\n", a->value.dv_time.tv_sec,
f95bc830 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
389void
390lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
391{
00e74b69 392 int res;
f95bc830 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);
00e74b69 441 res = fscanf(fp, " VALUE=%lf/>", value.v_double);
f95bc830 442 g_assert(res == 1);
443 }
444 else if(strcmp(type, "TIME") == 0) {
445 value = lttv_attribute_add(self, name, LTTV_TIME);
00e74b69 446 res = fscanf(fp, " SEC=%lu NSEC=%lu/>", &(value.v_time->tv_sec),
f95bc830 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
3e67c985 475static LttvAttribute *
476new_attribute (LttvAttribute *self)
477{
478 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
479}
480
f95bc830 481
dc877563 482static void
483attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 484{
dc877563 485 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 486
3e67c985 487 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
488 new_attribute;
489
dc877563 490 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
491 lttv_attribute_get_number;
f32847a1 492
dc877563 493 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
494 lttv_attribute_named;
f32847a1 495
dc877563 496 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
497 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 498
dc877563 499 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
500 LttvAttributeName name, LttvAttributeValue *v))
501 lttv_attribute_get_by_name;
f32847a1 502
dc877563 503 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
504 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 505
dc877563 506 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
507 lttv_attribute_remove;
f32847a1 508
dc877563 509 klass->remove_by_name = (void (*) (LttvIAttribute *self,
510 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 511
b445142a 512 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
513 LttvAttributeName name)) lttv_attribute_find_subdir;
5e2c04a2 514
f32847a1 515}
516
517
dc877563 518static void
519attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 520{
dc877563 521 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 522 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
523 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 524}
525
f32847a1 526
dc877563 527static void
528attribute_finalize (LttvAttribute *self)
f32847a1 529{
4d39be09 530 guint i;
2a2fa4f0 531 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
4d39be09 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);
dc877563 538 g_array_free(self->attributes, TRUE);
f32847a1 539}
540
f32847a1 541
dc877563 542static void
543attribute_class_init (LttvAttributeClass *klass)
f32847a1 544{
dc877563 545 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
3e67c985 546
ffd54a90 547 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 548}
549
ffd54a90 550GType
551lttv_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 */
00e74b69 564 (GInstanceInitFunc) attribute_instance_init, /* instance_init */
565 NULL /* value handling */
ffd54a90 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.05901 seconds and 4 git commands to generate.