2 #include <lttv/attribute.h>
5 typedef union _AttributeValue
{
9 unsigned long dv_ulong
;
19 typedef struct _Attribute
{
20 LttvAttributeName name
;
21 LttvAttributeType type
;
26 LttvAttributeValue
address_of_value(LttvAttributeType t
, AttributeValue
*v
)
28 LttvAttributeValue va
;
31 case LTTV_INT
: va
.v_int
= &v
->dv_int
; break;
32 case LTTV_UINT
: va
.v_uint
= &v
->dv_uint
; break;
33 case LTTV_LONG
: va
.v_long
= &v
->dv_long
; break;
34 case LTTV_ULONG
: va
.v_ulong
= &v
->dv_ulong
; break;
35 case LTTV_FLOAT
: va
.v_float
= &v
->dv_float
; break;
36 case LTTV_DOUBLE
: va
.v_double
= &v
->dv_double
; break;
37 case LTTV_TIME
: va
.v_time
= &v
->dv_time
; break;
38 case LTTV_POINTER
: va
.v_pointer
= &v
->dv_pointer
; break;
39 case LTTV_STRING
: va
.v_string
= &v
->dv_string
; break;
40 case LTTV_GOBJECT
: va
.v_gobject
= &v
->dv_gobject
; break;
46 AttributeValue
init_value(LttvAttributeType t
)
51 case LTTV_INT
: v
.dv_int
= 0; break;
52 case LTTV_UINT
: v
.dv_uint
= 0; break;
53 case LTTV_LONG
: v
.dv_long
= 0; break;
54 case LTTV_ULONG
: v
.dv_ulong
= 0; break;
55 case LTTV_FLOAT
: v
.dv_float
= 0; break;
56 case LTTV_DOUBLE
: v
.dv_double
= 0; break;
57 case LTTV_TIME
: v
.dv_time
.tv_sec
= 0; v
.dv_time
.tv_nsec
= 0; break;
58 case LTTV_POINTER
: v
.dv_pointer
= NULL
; break;
59 case LTTV_STRING
: v
.dv_string
= NULL
; break;
60 case LTTV_GOBJECT
: v
.dv_gobject
= NULL
; break;
67 lttv_attribute_get_number(LttvAttribute
*self
)
69 return self
->attributes
->len
;
74 lttv_attribute_named(LttvAttribute
*self
, gboolean
*homogeneous
)
82 lttv_attribute_get(LttvAttribute
*self
, unsigned i
, LttvAttributeName
*name
,
83 LttvAttributeValue
*v
)
87 a
= &g_array_index(self
->attributes
, Attribute
, i
);
89 *v
= address_of_value(a
->type
, &(a
->value
));
95 lttv_attribute_get_by_name(LttvAttribute
*self
, LttvAttributeName name
,
96 LttvAttributeValue
*v
)
104 p
= g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
105 if(p
== NULL
) return LTTV_NONE
;
107 i
= GPOINTER_TO_UINT(p
);
109 a
= &g_array_index(self
->attributes
, Attribute
, i
);
110 *v
= address_of_value(a
->type
, &(a
->value
));
116 lttv_attribute_add(LttvAttribute
*self
, LttvAttributeName name
,
123 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
124 if(i
!= 0) g_error("duplicate entry in attribute table");
128 a
.value
= init_value(t
);
129 g_array_append_val(self
->attributes
, a
);
130 i
= self
->attributes
->len
- 1;
131 pa
= &g_array_index(self
->attributes
, Attribute
, i
);
132 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(name
),
133 GUINT_TO_POINTER(i
+ 1));
134 return address_of_value(t
, &(pa
->value
));
138 /* Remove an attribute */
141 lttv_attribute_remove(LttvAttribute
*self
, unsigned i
)
145 a
= &g_array_index(self
->attributes
, Attribute
, i
);
147 /* Remove the array element and its entry in the name index */
149 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
150 g_array_remove_index_fast(self
->attributes
, i
);
152 /* The element used to replace the removed element has its index entry
153 all wrong now. Reinsert it with its new position. */
155 if(self
->attributes
->len
!= i
){
156 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
157 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(a
->name
), GUINT_TO_POINTER(i
+ 1));
162 lttv_attribute_remove_by_name(LttvAttribute
*self
, LttvAttributeName name
)
166 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
167 if(i
== 0) g_error("remove by name non existent attribute");
169 lttv_attribute_remove(self
, i
- 1);
172 /* Create an empty iattribute object and add it as an attribute under the
173 specified name, or return an existing iattribute attribute. If an
174 attribute of that name already exists but is not a GObject supporting the
175 iattribute interface, return NULL. */
177 /*CHECK*/LttvAttribute
*
178 lttv_attribute_find_subdir(LttvAttribute
*self
, LttvAttributeName name
)
186 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
188 a
= g_array_index(self
->attributes
, Attribute
, i
- 1);
189 if(a
.type
== LTTV_GOBJECT
&& LTTV_IS_IATTRIBUTE(a
.value
.dv_gobject
)) {
190 return LTTV_ATTRIBUTE(a
.value
.dv_gobject
);
194 new = g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
195 *(lttv_attribute_add(self
, name
, LTTV_GOBJECT
).v_gobject
) = G_OBJECT(new);
196 return (LttvAttribute
*)new;
200 lttv_attribute_find(LttvAttribute
*self
, LttvAttributeName name
,
201 LttvAttributeType t
, LttvAttributeValue
*v
)
207 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
209 a
= &g_array_index(self
->attributes
, Attribute
, i
- 1);
210 if(a
->type
!= t
) return FALSE
;
211 *v
= address_of_value(t
, &(a
->value
));
215 *v
= lttv_attribute_add(self
, name
, t
);
220 void lttv_attribute_recursive_free(LttvAttribute
*self
)
226 nb
= self
->attributes
->len
;
228 for(i
= 0 ; i
< nb
; i
++) {
229 a
= &g_array_index(self
->attributes
, Attribute
, i
);
230 if(a
->type
== LTTV_GOBJECT
&& LTTV_IS_ATTRIBUTE(a
->value
.dv_gobject
)) {
231 lttv_attribute_recursive_free((LttvAttribute
*)(a
->value
.dv_gobject
));
234 g_object_unref(self
);
238 void lttv_attribute_recursive_add(LttvAttribute
*dest
, LttvAttribute
*src
)
244 LttvAttributeValue value
;
246 nb
= src
->attributes
->len
;
248 for(i
= 0 ; i
< nb
; i
++) {
249 a
= &g_array_index(src
->attributes
, Attribute
, i
);
250 if(a
->type
== LTTV_GOBJECT
&& LTTV_IS_ATTRIBUTE(a
->value
.dv_gobject
)) {
251 lttv_attribute_recursive_add(
252 /*CHECK*/(LttvAttribute
*)lttv_attribute_find_subdir(dest
, a
->name
),
253 (LttvAttribute
*)(a
->value
.dv_gobject
));
256 g_assert(lttv_attribute_find(dest
, a
->name
, a
->type
, &value
));
259 *value
.v_int
+= a
->value
.dv_int
;
262 *value
.v_uint
+= a
->value
.dv_uint
;
265 *value
.v_long
+= a
->value
.dv_long
;
268 *value
.v_ulong
+= a
->value
.dv_ulong
;
271 *value
.v_float
+= a
->value
.dv_float
;
274 *value
.v_double
+= a
->value
.dv_double
;
277 *value
.v_time
= ltt_time_add(*value
.v_time
, a
->value
.dv_time
);
294 attribute_interface_init (gpointer g_iface
, gpointer iface_data
)
296 LttvIAttributeClass
*klass
= (LttvIAttributeClass
*)g_iface
;
298 klass
->get_number
= (unsigned int (*) (LttvIAttribute
*self
))
299 lttv_attribute_get_number
;
301 klass
->named
= (gboolean (*) (LttvIAttribute
*self
, gboolean
*homogeneous
))
302 lttv_attribute_named
;
304 klass
->get
= (LttvAttributeType (*) (LttvIAttribute
*self
, unsigned i
,
305 LttvAttributeName
*name
, LttvAttributeValue
*v
)) lttv_attribute_get
;
307 klass
->get_by_name
= (LttvAttributeType (*) (LttvIAttribute
*self
,
308 LttvAttributeName name
, LttvAttributeValue
*v
))
309 lttv_attribute_get_by_name
;
311 klass
->add
= (LttvAttributeValue (*) (LttvIAttribute
*self
,
312 LttvAttributeName name
, LttvAttributeType t
)) lttv_attribute_add
;
314 klass
->remove
= (void (*) (LttvIAttribute
*self
, unsigned i
))
315 lttv_attribute_remove
;
317 klass
->remove_by_name
= (void (*) (LttvIAttribute
*self
,
318 LttvAttributeName name
)) lttv_attribute_remove_by_name
;
320 klass
->find_subdir
= (LttvIAttribute
* (*) (LttvIAttribute
*self
,
321 LttvAttributeName name
)) lttv_attribute_find_subdir
;
326 attribute_instance_init (GTypeInstance
*instance
, gpointer g_class
)
328 LttvAttribute
*self
= (LttvAttribute
*)instance
;
329 self
->names
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
330 self
->attributes
= g_array_new(FALSE
, FALSE
, sizeof(Attribute
));
335 attribute_finalize (LttvAttribute
*self
)
337 g_hash_table_destroy(self
->names
);
338 g_critical("attribute_finalize()");
339 g_array_free(self
->attributes
, TRUE
);
340 G_OBJECT_CLASS(g_type_class_peek_parent(
341 g_type_class_peek(LTTV_ATTRIBUTE_TYPE
)))->finalize(G_OBJECT(self
));
346 attribute_class_init (LttvAttributeClass
*klass
)
348 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
350 gobject_class
->finalize
= (void (*)(GObject
*self
))attribute_finalize
;
354 lttv_attribute_get_type (void)
356 static GType type
= 0;
358 static const GTypeInfo info
= {
359 sizeof (LttvAttributeClass
),
360 NULL
, /* base_init */
361 NULL
, /* base_finalize */
362 (GClassInitFunc
) attribute_class_init
, /* class_init */
363 NULL
, /* class_finalize */
364 NULL
, /* class_data */
365 sizeof (LttvAttribute
),
367 (GInstanceInitFunc
) attribute_instance_init
/* instance_init */
370 static const GInterfaceInfo iattribute_info
= {
371 (GInterfaceInitFunc
) attribute_interface_init
, /* interface_init */
372 NULL
, /* interface_finalize */
373 NULL
/* interface_data */
376 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvAttributeType", &info
,
378 g_type_add_interface_static (type
, LTTV_IATTRIBUTE_TYPE
, &iattribute_info
);