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