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