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