1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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;
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.
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,
19 #include <lttv/attribute.h>
22 typedef union _AttributeValue
{
26 unsigned long dv_ulong
;
36 typedef struct _Attribute
{
37 LttvAttributeName name
;
38 LttvAttributeType type
;
43 LttvAttributeValue
address_of_value(LttvAttributeType t
, AttributeValue
*v
)
45 LttvAttributeValue va
;
48 case LTTV_INT
: va
.v_int
= &v
->dv_int
; break;
49 case LTTV_UINT
: va
.v_uint
= &v
->dv_uint
; break;
50 case LTTV_LONG
: va
.v_long
= &v
->dv_long
; break;
51 case LTTV_ULONG
: va
.v_ulong
= &v
->dv_ulong
; break;
52 case LTTV_FLOAT
: va
.v_float
= &v
->dv_float
; break;
53 case LTTV_DOUBLE
: va
.v_double
= &v
->dv_double
; break;
54 case LTTV_TIME
: va
.v_time
= &v
->dv_time
; break;
55 case LTTV_POINTER
: va
.v_pointer
= &v
->dv_pointer
; break;
56 case LTTV_STRING
: va
.v_string
= &v
->dv_string
; break;
57 case LTTV_GOBJECT
: va
.v_gobject
= &v
->dv_gobject
; break;
63 AttributeValue
init_value(LttvAttributeType t
)
68 case LTTV_INT
: v
.dv_int
= 0; break;
69 case LTTV_UINT
: v
.dv_uint
= 0; break;
70 case LTTV_LONG
: v
.dv_long
= 0; break;
71 case LTTV_ULONG
: v
.dv_ulong
= 0; break;
72 case LTTV_FLOAT
: v
.dv_float
= 0; break;
73 case LTTV_DOUBLE
: v
.dv_double
= 0; break;
74 case LTTV_TIME
: v
.dv_time
.tv_sec
= 0; v
.dv_time
.tv_nsec
= 0; break;
75 case LTTV_POINTER
: v
.dv_pointer
= NULL
; break;
76 case LTTV_STRING
: v
.dv_string
= NULL
; break;
77 case LTTV_GOBJECT
: v
.dv_gobject
= NULL
; break;
84 lttv_attribute_get_number(LttvAttribute
*self
)
86 return self
->attributes
->len
;
91 lttv_attribute_named(LttvAttribute
*self
, gboolean
*homogeneous
)
99 lttv_attribute_get(LttvAttribute
*self
, unsigned i
, LttvAttributeName
*name
,
100 LttvAttributeValue
*v
)
104 a
= &g_array_index(self
->attributes
, Attribute
, i
);
106 *v
= address_of_value(a
->type
, &(a
->value
));
112 lttv_attribute_get_by_name(LttvAttribute
*self
, LttvAttributeName name
,
113 LttvAttributeValue
*v
)
121 p
= g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
122 if(p
== NULL
) return LTTV_NONE
;
124 i
= GPOINTER_TO_UINT(p
);
126 a
= &g_array_index(self
->attributes
, Attribute
, i
);
127 *v
= address_of_value(a
->type
, &(a
->value
));
133 lttv_attribute_add(LttvAttribute
*self
, LttvAttributeName name
,
140 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
141 if(i
!= 0) g_error("duplicate entry in attribute table");
145 a
.value
= init_value(t
);
146 g_array_append_val(self
->attributes
, a
);
147 i
= self
->attributes
->len
- 1;
148 pa
= &g_array_index(self
->attributes
, Attribute
, i
);
149 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(name
),
150 GUINT_TO_POINTER(i
+ 1));
151 return address_of_value(t
, &(pa
->value
));
155 /* Remove an attribute */
158 lttv_attribute_remove(LttvAttribute
*self
, unsigned i
)
162 a
= &g_array_index(self
->attributes
, Attribute
, i
);
164 /* Remove the array element and its entry in the name index */
166 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
167 g_array_remove_index_fast(self
->attributes
, i
);
169 /* The element used to replace the removed element has its index entry
170 all wrong now. Reinsert it with its new position. */
172 if(self
->attributes
->len
!= i
){
173 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
174 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(a
->name
), GUINT_TO_POINTER(i
+ 1));
179 lttv_attribute_remove_by_name(LttvAttribute
*self
, LttvAttributeName name
)
183 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
184 if(i
== 0) g_error("remove by name non existent attribute");
186 lttv_attribute_remove(self
, i
- 1);
189 /* Create an empty iattribute object and add it as an attribute under the
190 specified name, or return an existing iattribute attribute. If an
191 attribute of that name already exists but is not a GObject supporting the
192 iattribute interface, return NULL. */
194 /*CHECK*/LttvAttribute
*
195 lttv_attribute_find_subdir(LttvAttribute
*self
, LttvAttributeName name
)
203 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
205 a
= g_array_index(self
->attributes
, Attribute
, i
- 1);
206 if(a
.type
== LTTV_GOBJECT
&& LTTV_IS_IATTRIBUTE(a
.value
.dv_gobject
)) {
207 return LTTV_ATTRIBUTE(a
.value
.dv_gobject
);
211 new = g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
212 *(lttv_attribute_add(self
, name
, LTTV_GOBJECT
).v_gobject
) = G_OBJECT(new);
213 return (LttvAttribute
*)new;
217 lttv_attribute_find(LttvAttribute
*self
, LttvAttributeName name
,
218 LttvAttributeType t
, LttvAttributeValue
*v
)
224 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
226 a
= &g_array_index(self
->attributes
, Attribute
, i
- 1);
227 if(a
->type
!= t
) return FALSE
;
228 *v
= address_of_value(t
, &(a
->value
));
232 *v
= lttv_attribute_add(self
, name
, t
);
237 void lttv_attribute_recursive_free(LttvAttribute
*self
)
243 nb
= self
->attributes
->len
;
245 for(i
= 0 ; i
< nb
; i
++) {
246 a
= &g_array_index(self
->attributes
, Attribute
, i
);
247 if(a
->type
== LTTV_GOBJECT
&& LTTV_IS_ATTRIBUTE(a
->value
.dv_gobject
)) {
248 lttv_attribute_recursive_free((LttvAttribute
*)(a
->value
.dv_gobject
));
251 g_object_unref(self
);
255 void lttv_attribute_recursive_add(LttvAttribute
*dest
, LttvAttribute
*src
)
261 LttvAttributeValue value
;
263 nb
= src
->attributes
->len
;
265 for(i
= 0 ; i
< nb
; i
++) {
266 a
= &g_array_index(src
->attributes
, Attribute
, i
);
267 if(a
->type
== LTTV_GOBJECT
&& LTTV_IS_ATTRIBUTE(a
->value
.dv_gobject
)) {
268 lttv_attribute_recursive_add(
269 /*CHECK*/(LttvAttribute
*)lttv_attribute_find_subdir(dest
, a
->name
),
270 (LttvAttribute
*)(a
->value
.dv_gobject
));
273 g_assert(lttv_attribute_find(dest
, a
->name
, a
->type
, &value
));
276 *value
.v_int
+= a
->value
.dv_int
;
279 *value
.v_uint
+= a
->value
.dv_uint
;
282 *value
.v_long
+= a
->value
.dv_long
;
285 *value
.v_ulong
+= a
->value
.dv_ulong
;
288 *value
.v_float
+= a
->value
.dv_float
;
291 *value
.v_double
+= a
->value
.dv_double
;
294 *value
.v_time
= ltt_time_add(*value
.v_time
, a
->value
.dv_time
);
311 attribute_interface_init (gpointer g_iface
, gpointer iface_data
)
313 LttvIAttributeClass
*klass
= (LttvIAttributeClass
*)g_iface
;
315 klass
->get_number
= (unsigned int (*) (LttvIAttribute
*self
))
316 lttv_attribute_get_number
;
318 klass
->named
= (gboolean (*) (LttvIAttribute
*self
, gboolean
*homogeneous
))
319 lttv_attribute_named
;
321 klass
->get
= (LttvAttributeType (*) (LttvIAttribute
*self
, unsigned i
,
322 LttvAttributeName
*name
, LttvAttributeValue
*v
)) lttv_attribute_get
;
324 klass
->get_by_name
= (LttvAttributeType (*) (LttvIAttribute
*self
,
325 LttvAttributeName name
, LttvAttributeValue
*v
))
326 lttv_attribute_get_by_name
;
328 klass
->add
= (LttvAttributeValue (*) (LttvIAttribute
*self
,
329 LttvAttributeName name
, LttvAttributeType t
)) lttv_attribute_add
;
331 klass
->remove
= (void (*) (LttvIAttribute
*self
, unsigned i
))
332 lttv_attribute_remove
;
334 klass
->remove_by_name
= (void (*) (LttvIAttribute
*self
,
335 LttvAttributeName name
)) lttv_attribute_remove_by_name
;
337 klass
->find_subdir
= (LttvIAttribute
* (*) (LttvIAttribute
*self
,
338 LttvAttributeName name
)) lttv_attribute_find_subdir
;
343 attribute_instance_init (GTypeInstance
*instance
, gpointer g_class
)
345 LttvAttribute
*self
= (LttvAttribute
*)instance
;
346 self
->names
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
347 self
->attributes
= g_array_new(FALSE
, FALSE
, sizeof(Attribute
));
352 attribute_finalize (LttvAttribute
*self
)
354 g_hash_table_destroy(self
->names
);
355 g_critical("attribute_finalize()");
356 g_array_free(self
->attributes
, TRUE
);
357 G_OBJECT_CLASS(g_type_class_peek_parent(
358 g_type_class_peek(LTTV_ATTRIBUTE_TYPE
)))->finalize(G_OBJECT(self
));
363 attribute_class_init (LttvAttributeClass
*klass
)
365 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
367 gobject_class
->finalize
= (void (*)(GObject
*self
))attribute_finalize
;
371 lttv_attribute_get_type (void)
373 static GType type
= 0;
375 static const GTypeInfo info
= {
376 sizeof (LttvAttributeClass
),
377 NULL
, /* base_init */
378 NULL
, /* base_finalize */
379 (GClassInitFunc
) attribute_class_init
, /* class_init */
380 NULL
, /* class_finalize */
381 NULL
, /* class_data */
382 sizeof (LttvAttribute
),
384 (GInstanceInitFunc
) attribute_instance_init
/* instance_init */
387 static const GInterfaceInfo iattribute_info
= {
388 (GInterfaceInitFunc
) attribute_interface_init
, /* interface_init */
389 NULL
, /* interface_finalize */
390 NULL
/* interface_data */
393 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvAttributeType", &info
,
395 g_type_add_interface_static (type
, LTTV_IATTRIBUTE_TYPE
, &iattribute_info
);