fix __inline -> __inline__
[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 static __inline__ LttvAttributeValue address_of_value(LttvAttributeType t,
45 AttributeValue *v)
46 {
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;
60 case LTTV_NONE: break;
61 }
62 return va;
63 }
64
65
66 AttributeValue 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;
81 case LTTV_NONE: break;
82 }
83 return v;
84 }
85
86
87 unsigned int
88 lttv_attribute_get_number(LttvAttribute *self)
89 {
90 return self->attributes->len;
91 }
92
93
94 gboolean
95 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
96 {
97 *homogeneous = FALSE;
98 return TRUE;
99 }
100
101
102 LttvAttributeType
103 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
104 LttvAttributeValue *v)
105 {
106 Attribute *a;
107
108 a = &g_array_index(self->attributes, Attribute, i);
109 *name = a->name;
110 *v = address_of_value(a->type, &(a->value));
111 return a->type;
112 }
113
114
115 LttvAttributeType
116 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
117 LttvAttributeValue *v)
118 {
119 Attribute *a;
120
121 unsigned i;
122
123 gpointer p;
124
125 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
126 if(p == NULL) return LTTV_NONE;
127
128 i = GPOINTER_TO_UINT(p);
129 i--;
130 a = &g_array_index(self->attributes, Attribute, i);
131 *v = address_of_value(a->type, &(a->value));
132 return a->type;
133 }
134
135
136 LttvAttributeValue
137 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
138 LttvAttributeType t)
139 {
140 unsigned i;
141
142 Attribute a, *pa;
143
144 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
145 if(i != 0) g_error("duplicate entry in attribute table");
146
147 a.name = name;
148 a.type = t;
149 a.value = init_value(t);
150 g_array_append_val(self->attributes, a);
151 i = self->attributes->len - 1;
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));
156 }
157
158
159 /* Remove an attribute */
160
161 void
162 lttv_attribute_remove(LttvAttribute *self, unsigned i)
163 {
164 Attribute *a;
165
166 a = &g_array_index(self->attributes, Attribute, i);
167
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
172 /* Remove the array element and its entry in the name index */
173
174 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
175 g_array_remove_index_fast(self->attributes, i);
176
177 /* The element used to replace the removed element has its index entry
178 all wrong now. Reinsert it with its new position. */
179
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 }
184 }
185
186 void
187 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
188 {
189 unsigned i;
190
191 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
192 if(i == 0) g_error("remove by name non existent attribute");
193
194 lttv_attribute_remove(self, i - 1);
195 }
196
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. */
201
202 /*CHECK*/LttvAttribute*
203 lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
204 {
205 unsigned i;
206
207 Attribute a;
208
209 LttvAttribute *new;
210
211 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
212 if(i != 0) {
213 a = g_array_index(self->attributes, Attribute, i - 1);
214 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
215 return LTTV_ATTRIBUTE(a.value.dv_gobject);
216 }
217 else return NULL;
218 }
219 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
220 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
221 return (LttvAttribute *)new;
222 }
223
224 gboolean
225 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
226 LttvAttributeType t, LttvAttributeValue *v)
227 {
228 unsigned i;
229
230 Attribute *a;
231
232 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
233 if(i != 0) {
234 a = &g_array_index(self->attributes, Attribute, i - 1);
235 if(a->type != t) return FALSE;
236 *v = address_of_value(t, &(a->value));
237 return TRUE;
238 }
239
240 *v = lttv_attribute_add(self, name, t);
241 return TRUE;
242 }
243
244
245 /*void lttv_attribute_recursive_free(LttvAttribute *self)
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);
260 }*/
261
262
263 void 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) {
283 case LTTV_INT:
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:
302 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
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
318 static void
319 print_indent(FILE *fp, int pos)
320 {
321 int i;
322
323 for(i = 0 ; i < pos ; i++) putc(' ', fp);
324 }
325
326
327 void
328 lttv_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);
340 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
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:
367 fprintf(fp, "TYPE=TIME SEC=%lu NSEC=%lu/>\n", a->value.dv_time.tv_sec,
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
390 void
391 lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
392 {
393 int res;
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);
442 res = fscanf(fp, " VALUE=%lf/>", value.v_double);
443 g_assert(res == 1);
444 }
445 else if(strcmp(type, "TIME") == 0) {
446 value = lttv_attribute_add(self, name, LTTV_TIME);
447 res = fscanf(fp, " SEC=%lu NSEC=%lu/>", &(value.v_time->tv_sec),
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
476 static LttvAttribute *
477 new_attribute (LttvAttribute *self)
478 {
479 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
480 }
481
482
483 static void
484 attribute_interface_init (gpointer g_iface, gpointer iface_data)
485 {
486 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
487
488 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
489 new_attribute;
490
491 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
492 lttv_attribute_get_number;
493
494 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
495 lttv_attribute_named;
496
497 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
498 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
499
500 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
501 LttvAttributeName name, LttvAttributeValue *v))
502 lttv_attribute_get_by_name;
503
504 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
505 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
506
507 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
508 lttv_attribute_remove;
509
510 klass->remove_by_name = (void (*) (LttvIAttribute *self,
511 LttvAttributeName name)) lttv_attribute_remove_by_name;
512
513 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
514 LttvAttributeName name)) lttv_attribute_find_subdir;
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,
523 g_direct_equal);
524 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
525 }
526
527
528 static void
529 attribute_finalize (LttvAttribute *self)
530 {
531 guint i;
532 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
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);
539 g_array_free(self->attributes, TRUE);
540 }
541
542
543 static void
544 attribute_class_init (LttvAttributeClass *klass)
545 {
546 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
547
548 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
549 }
550
551 GType
552 lttv_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 */
565 (GInstanceInitFunc) attribute_instance_init, /* instance_init */
566 NULL /* value handling */
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.04038 seconds and 4 git commands to generate.