uninitialized variables checked. Also change two if/else if functions for switch
[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
fcdf0ec2 19#include <lttv/attribute.h>
b445142a 20#include <ltt/ltt.h>
f32847a1 21
dc877563 22typedef 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;
308711e5 29 LttTime dv_time;
dc877563 30 gpointer dv_pointer;
31 char *dv_string;
ffd54a90 32 GObject *dv_gobject;
dc877563 33} AttributeValue;
34
35
36typedef struct _Attribute {
37 LttvAttributeName name;
38 LttvAttributeType type;
39 AttributeValue value;
40} Attribute;
41
42
ffd54a90 43LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
dc877563 44{
ffd54a90 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}
dc877563 61
dc877563 62
ffd54a90 63AttributeValue 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;
dc877563 78 }
ffd54a90 79 return v;
f32847a1 80}
81
82
dc877563 83unsigned int
84lttv_attribute_get_number(LttvAttribute *self)
85{
86 return self->attributes->len;
f32847a1 87}
88
89
dc877563 90gboolean
91lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
92{
93 *homogeneous = FALSE;
94 return TRUE;
f32847a1 95}
96
97
dc877563 98LttvAttributeType
99lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
100 LttvAttributeValue *v)
101{
102 Attribute *a;
f32847a1 103
dc877563 104 a = &g_array_index(self->attributes, Attribute, i);
105 *name = a->name;
ffd54a90 106 *v = address_of_value(a->type, &(a->value));
dc877563 107 return a->type;
f32847a1 108}
109
110
dc877563 111LttvAttributeType
112lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
113 LttvAttributeValue *v)
114{
115 Attribute *a;
f32847a1 116
dc877563 117 unsigned i;
f32847a1 118
ffd54a90 119 gpointer p;
120
121 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
122 if(p == NULL) return LTTV_NONE;
f32847a1 123
ba576a78 124 i = GPOINTER_TO_UINT(p);
dc877563 125 i--;
126 a = &g_array_index(self->attributes, Attribute, i);
ffd54a90 127 *v = address_of_value(a->type, &(a->value));
dc877563 128 return a->type;
f32847a1 129}
130
f32847a1 131
dc877563 132LttvAttributeValue
133lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
134 LttvAttributeType t)
135{
136 unsigned i;
f32847a1 137
dc877563 138 Attribute a, *pa;
f32847a1 139
ffd54a90 140 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 141 if(i != 0) g_error("duplicate entry in attribute table");
f32847a1 142
ffd54a90 143 a.name = name;
144 a.type = t;
145 a.value = init_value(t);
dc877563 146 g_array_append_val(self->attributes, a);
147 i = self->attributes->len - 1;
ffd54a90 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));
f32847a1 152}
153
154
dc877563 155/* Remove an attribute */
f32847a1 156
dc877563 157void
158lttv_attribute_remove(LttvAttribute *self, unsigned i)
f32847a1 159{
dc877563 160 Attribute *a;
f32847a1 161
dc877563 162 a = &g_array_index(self->attributes, Attribute, i);
f32847a1 163
c47a6dc6 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
dc877563 168 /* Remove the array element and its entry in the name index */
f32847a1 169
ffd54a90 170 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
dc877563 171 g_array_remove_index_fast(self->attributes, i);
f32847a1 172
dc877563 173 /* The element used to replace the removed element has its index entry
174 all wrong now. Reinsert it with its new position. */
f32847a1 175
c6bc9cb9 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 }
f32847a1 180}
181
dc877563 182void
183lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
184{
185 unsigned i;
f32847a1 186
ffd54a90 187 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 188 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 189
dc877563 190 lttv_attribute_remove(self, i - 1);
f32847a1 191}
192
dc877563 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. */
f32847a1 197
b445142a 198/*CHECK*/LttvAttribute*
199lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 200{
dc877563 201 unsigned i;
f32847a1 202
dc877563 203 Attribute a;
f32847a1 204
dc877563 205 LttvAttribute *new;
a43d67ba 206
ffd54a90 207 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 208 if(i != 0) {
209 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 210 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
b445142a 211 return LTTV_ATTRIBUTE(a.value.dv_gobject);
dc877563 212 }
213 else return NULL;
f32847a1 214 }
ffd54a90 215 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
216 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
b445142a 217 return (LttvAttribute *)new;
f32847a1 218}
219
dc877563 220gboolean
221lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
222 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 223{
dc877563 224 unsigned i;
f32847a1 225
dc877563 226 Attribute *a;
f32847a1 227
ffd54a90 228 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 229 if(i != 0) {
230 a = &g_array_index(self->attributes, Attribute, i - 1);
231 if(a->type != t) return FALSE;
ffd54a90 232 *v = address_of_value(t, &(a->value));
dc877563 233 return TRUE;
234 }
f32847a1 235
dc877563 236 *v = lttv_attribute_add(self, name, t);
237 return TRUE;
f32847a1 238}
239
f32847a1 240
c47a6dc6 241/*void lttv_attribute_recursive_free(LttvAttribute *self)
b445142a 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);
c47a6dc6 256}*/
b445142a 257
258
259void 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) {
c47a6dc6 279 case LTTV_INT:
b445142a 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:
308711e5 298 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
b445142a 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
f95bc830 314static void
315print_indent(FILE *fp, int pos)
316{
317 int i;
318
319 for(i = 0 ; i < pos ; i++) putc(' ', fp);
320}
321
322
323void
324lttv_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);
5bf80c50 336 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
f95bc830 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
386void
387lttv_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
3e67c985 474static LttvAttribute *
475new_attribute (LttvAttribute *self)
476{
477 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
478}
479
f95bc830 480
dc877563 481static void
482attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 483{
dc877563 484 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 485
3e67c985 486 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
487 new_attribute;
488
dc877563 489 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
490 lttv_attribute_get_number;
f32847a1 491
dc877563 492 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
493 lttv_attribute_named;
f32847a1 494
dc877563 495 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
496 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 497
dc877563 498 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
499 LttvAttributeName name, LttvAttributeValue *v))
500 lttv_attribute_get_by_name;
f32847a1 501
dc877563 502 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
503 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 504
dc877563 505 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
506 lttv_attribute_remove;
f32847a1 507
dc877563 508 klass->remove_by_name = (void (*) (LttvIAttribute *self,
509 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 510
b445142a 511 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
512 LttvAttributeName name)) lttv_attribute_find_subdir;
5e2c04a2 513
f32847a1 514}
515
516
dc877563 517static void
518attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 519{
dc877563 520 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 521 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
522 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 523}
524
f32847a1 525
dc877563 526static void
527attribute_finalize (LttvAttribute *self)
f32847a1 528{
4d39be09 529 guint i;
2a2fa4f0 530 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
4d39be09 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);
dc877563 537 g_array_free(self->attributes, TRUE);
f32847a1 538}
539
f32847a1 540
dc877563 541static void
542attribute_class_init (LttvAttributeClass *klass)
f32847a1 543{
dc877563 544 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
3e67c985 545
ffd54a90 546 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 547}
548
ffd54a90 549GType
550lttv_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.055997 seconds and 4 git commands to generate.