last mod doc
[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
dc877563 164 /* Remove the array element and its entry in the name index */
f32847a1 165
ffd54a90 166 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
dc877563 167 g_array_remove_index_fast(self->attributes, i);
f32847a1 168
dc877563 169 /* The element used to replace the removed element has its index entry
170 all wrong now. Reinsert it with its new position. */
f32847a1 171
c6bc9cb9 172 if(self->attributes->len != i){
173 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
174 g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
175 }
f32847a1 176}
177
dc877563 178void
179lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
180{
181 unsigned i;
f32847a1 182
ffd54a90 183 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 184 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 185
dc877563 186 lttv_attribute_remove(self, i - 1);
f32847a1 187}
188
dc877563 189/* Create an empty iattribute object and add it as an attribute under the
190 specified name, or return an existing iattribute attribute. If an
191 attribute of that name already exists but is not a GObject supporting the
192 iattribute interface, return NULL. */
f32847a1 193
b445142a 194/*CHECK*/LttvAttribute*
195lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 196{
dc877563 197 unsigned i;
f32847a1 198
dc877563 199 Attribute a;
f32847a1 200
dc877563 201 LttvAttribute *new;
a43d67ba 202
ffd54a90 203 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 204 if(i != 0) {
205 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 206 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
b445142a 207 return LTTV_ATTRIBUTE(a.value.dv_gobject);
dc877563 208 }
209 else return NULL;
f32847a1 210 }
ffd54a90 211 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
212 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
b445142a 213 return (LttvAttribute *)new;
f32847a1 214}
215
dc877563 216gboolean
217lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
218 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 219{
dc877563 220 unsigned i;
f32847a1 221
dc877563 222 Attribute *a;
f32847a1 223
ffd54a90 224 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 225 if(i != 0) {
226 a = &g_array_index(self->attributes, Attribute, i - 1);
227 if(a->type != t) return FALSE;
ffd54a90 228 *v = address_of_value(t, &(a->value));
dc877563 229 return TRUE;
230 }
f32847a1 231
dc877563 232 *v = lttv_attribute_add(self, name, t);
233 return TRUE;
f32847a1 234}
235
f32847a1 236
b445142a 237void lttv_attribute_recursive_free(LttvAttribute *self)
238{
239 int i, nb;
240
241 Attribute *a;
242
243 nb = self->attributes->len;
244
245 for(i = 0 ; i < nb ; i++) {
246 a = &g_array_index(self->attributes, Attribute, i);
247 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
248 lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
249 }
250 }
251 g_object_unref(self);
252}
253
254
255void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
256{
257 int i, nb;
258
259 Attribute *a;
260
261 LttvAttributeValue value;
262
263 nb = src->attributes->len;
264
265 for(i = 0 ; i < nb ; i++) {
266 a = &g_array_index(src->attributes, Attribute, i);
267 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
268 lttv_attribute_recursive_add(
269 /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
270 (LttvAttribute *)(a->value.dv_gobject));
271 }
272 else {
273 g_assert(lttv_attribute_find(dest, a->name, a->type, &value));
274 switch(a->type) {
275 case LTTV_INT:
276 *value.v_int += a->value.dv_int;
277 break;
278 case LTTV_UINT:
279 *value.v_uint += a->value.dv_uint;
280 break;
281 case LTTV_LONG:
282 *value.v_long += a->value.dv_long;
283 break;
284 case LTTV_ULONG:
285 *value.v_ulong += a->value.dv_ulong;
286 break;
287 case LTTV_FLOAT:
288 *value.v_float += a->value.dv_float;
289 break;
290 case LTTV_DOUBLE:
291 *value.v_double += a->value.dv_double;
292 break;
293 case LTTV_TIME:
308711e5 294 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
b445142a 295 break;
296 case LTTV_POINTER:
297 break;
298 case LTTV_STRING:
299 break;
300 case LTTV_GOBJECT:
301 break;
302 case LTTV_NONE:
303 break;
304 }
305 }
306 }
307}
308
309
f95bc830 310static void
311print_indent(FILE *fp, int pos)
312{
313 int i;
314
315 for(i = 0 ; i < pos ; i++) putc(' ', fp);
316}
317
318
319void
320lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent)
321{
322 int i, nb;
323
324 Attribute *a;
325
326 nb = self->attributes->len;
327
328 fprintf(fp,"<ATTRS>\n");
329 for(i = 0 ; i < nb ; i++) {
330 a = &g_array_index(self->attributes, Attribute, i);
331 print_indent(fp, pos);
5bf80c50 332 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
f95bc830 333 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
334 fprintf(fp, "TYPE=ATTRS>");
335 lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp,
336 pos + indent, indent);
337 }
338 else {
339 switch(a->type) {
340 case LTTV_INT:
341 fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int);
342 break;
343 case LTTV_UINT:
344 fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint);
345 break;
346 case LTTV_LONG:
347 fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long);
348 break;
349 case LTTV_ULONG:
350 fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong);
351 break;
352 case LTTV_FLOAT:
353 fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float);
354 break;
355 case LTTV_DOUBLE:
356 fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double);
357 break;
358 case LTTV_TIME:
359 fprintf(fp, "TYPE=TIME SEC=%u NSEC=%u/>\n", a->value.dv_time.tv_sec,
360 a->value.dv_time.tv_nsec);
361 break;
362 case LTTV_POINTER:
363 fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer);
364 break;
365 case LTTV_STRING:
366 fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string);
367 break;
368 case LTTV_GOBJECT:
369 fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject);
370 break;
371 case LTTV_NONE:
372 fprintf(fp, "TYPE=NONE/>\n");
373 break;
374 }
375 }
376 }
377 print_indent(fp, pos);
378 fprintf(fp,"</ATTRS>\n");
379}
380
381
382void
383lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
384{
385 int i, nb, res;
386
387 Attribute *a;
388
389 char buffer[256], type[10];
390
391 LttvAttributeName name;
392
393 LttvAttributeValue value;
394
395 LttvAttribute *subtree;
396
397 fscanf(fp,"<ATTRS>");
398 while(1) {
399 res = fscanf(fp, "<ATTR NAME=\"%256[^\"]\" TYPE=%10[^ >]", buffer, type);
400 g_assert(res == 2);
401 name = g_quark_from_string(buffer);
402 if(strcmp(type, "ATTRS") == 0) {
403 fscanf(fp, ">");
404 subtree = lttv_attribute_find_subdir(self, name);
405 lttv_attribute_read_xml(subtree, fp);
406 }
407 else if(strcmp(type, "INT") == 0) {
408 value = lttv_attribute_add(self, name, LTTV_INT);
409 res = fscanf(fp, " VALUE=%d/>", value.v_int);
410 g_assert(res == 1);
411 }
412 else if(strcmp(type, "UINT") == 0) {
413 value = lttv_attribute_add(self, name, LTTV_UINT);
414 res = fscanf(fp, " VALUE=%u/>", value.v_uint);
415 g_assert(res == 1);
416 }
417 else if(strcmp(type, "LONG") == 0) {
418 value = lttv_attribute_add(self, name, LTTV_LONG);
419 res = fscanf(fp, " VALUE=%ld/>", value.v_long);
420 g_assert(res == 1);
421 }
422 else if(strcmp(type, "ULONG") == 0) {
423 value = lttv_attribute_add(self, name, LTTV_ULONG);
424 res = fscanf(fp, " VALUE=%lu/>", value.v_ulong);
425 g_assert(res == 1);
426 }
427 else if(strcmp(type, "FLOAT") == 0) {
428 float d;
429 value = lttv_attribute_add(self, name, LTTV_FLOAT);
430 res = fscanf(fp, " VALUE=%f/>", &d);
431 *(value.v_float) = d;
432 g_assert(res == 1);
433 }
434 else if(strcmp(type, "DOUBLE") == 0) {
435 value = lttv_attribute_add(self, name, LTTV_DOUBLE);
436 res = fscanf(fp, " VALUE=%f/>", value.v_double);
437 g_assert(res == 1);
438 }
439 else if(strcmp(type, "TIME") == 0) {
440 value = lttv_attribute_add(self, name, LTTV_TIME);
441 res = fscanf(fp, " SEC=%u NSEC=%u/>", &(value.v_time->tv_sec),
442 &(value.v_time->tv_nsec));
443 g_assert(res == 2);
444 }
445 else if(strcmp(type, "POINTER") == 0) {
446 value = lttv_attribute_add(self, name, LTTV_POINTER);
447 res = fscanf(fp, " VALUE=%p/>", value.v_pointer);
448 g_error("Cannot read a pointer");
449 }
450 else if(strcmp(type, "STRING") == 0) {
451 value = lttv_attribute_add(self, name, LTTV_STRING);
452 res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer);
453 *(value.v_string) = g_strdup(buffer);
454 g_assert(res == 1);
455 }
456 else if(strcmp(type, "GOBJECT") == 0) {
457 value = lttv_attribute_add(self, name, LTTV_GOBJECT);
458 res = fscanf(fp, " VALUE=%p/>", value.v_gobject);
459 g_error("Cannot read a pointer");
460 }
461 else if(strcmp(type, "NONE") == 0) {
462 value = lttv_attribute_add(self, name, LTTV_NONE);
463 fscanf(fp, "/>");
464 }
465 else g_error("Unknown type to read");
466 }
467 fscanf(fp,"</ATTRS>");
468}
469
3e67c985 470static LttvAttribute *
471new_attribute (LttvAttribute *self)
472{
473 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
474}
475
f95bc830 476
dc877563 477static void
478attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 479{
dc877563 480 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 481
3e67c985 482 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
483 new_attribute;
484
dc877563 485 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
486 lttv_attribute_get_number;
f32847a1 487
dc877563 488 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
489 lttv_attribute_named;
f32847a1 490
dc877563 491 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
492 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 493
dc877563 494 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
495 LttvAttributeName name, LttvAttributeValue *v))
496 lttv_attribute_get_by_name;
f32847a1 497
dc877563 498 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
499 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 500
dc877563 501 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
502 lttv_attribute_remove;
f32847a1 503
dc877563 504 klass->remove_by_name = (void (*) (LttvIAttribute *self,
505 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 506
b445142a 507 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
508 LttvAttributeName name)) lttv_attribute_find_subdir;
5e2c04a2 509
f32847a1 510}
511
512
dc877563 513static void
514attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 515{
dc877563 516 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 517 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
518 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 519}
520
f32847a1 521
dc877563 522static void
523attribute_finalize (LttvAttribute *self)
f32847a1 524{
ba576a78 525 g_hash_table_destroy(self->names);
2a2fa4f0 526 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
dc877563 527 g_array_free(self->attributes, TRUE);
b445142a 528 G_OBJECT_CLASS(g_type_class_peek_parent(
529 g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
f32847a1 530}
531
f32847a1 532
dc877563 533static void
534attribute_class_init (LttvAttributeClass *klass)
f32847a1 535{
dc877563 536 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
3e67c985 537
ffd54a90 538 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 539}
540
ffd54a90 541GType
542lttv_attribute_get_type (void)
543{
544 static GType type = 0;
545 if (type == 0) {
546 static const GTypeInfo info = {
547 sizeof (LttvAttributeClass),
548 NULL, /* base_init */
549 NULL, /* base_finalize */
550 (GClassInitFunc) attribute_class_init, /* class_init */
551 NULL, /* class_finalize */
552 NULL, /* class_data */
553 sizeof (LttvAttribute),
554 0, /* n_preallocs */
555 (GInstanceInitFunc) attribute_instance_init /* instance_init */
556 };
557
558 static const GInterfaceInfo iattribute_info = {
559 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
560 NULL, /* interface_finalize */
561 NULL /* interface_data */
562 };
563
564 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
565 0);
566 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
567 }
568 return type;
569}
570
571
This page took 0.053957 seconds and 4 git commands to generate.