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