2 #include <lttv/attribute.h>
4 typedef union _AttributeValue
{
8 unsigned long dv_ulong
;
18 typedef struct _Attribute
{
19 LttvAttributeName name
;
20 LttvAttributeType type
;
25 LttvAttributeValue
address_of_value(LttvAttributeType t
, AttributeValue
*v
)
27 LttvAttributeValue va
;
30 case LTTV_INT
: va
.v_int
= &v
->dv_int
; break;
31 case LTTV_UINT
: va
.v_uint
= &v
->dv_uint
; break;
32 case LTTV_LONG
: va
.v_long
= &v
->dv_long
; break;
33 case LTTV_ULONG
: va
.v_ulong
= &v
->dv_ulong
; break;
34 case LTTV_FLOAT
: va
.v_float
= &v
->dv_float
; break;
35 case LTTV_DOUBLE
: va
.v_double
= &v
->dv_double
; break;
36 case LTTV_TIME
: va
.v_time
= &v
->dv_time
; break;
37 case LTTV_POINTER
: va
.v_pointer
= &v
->dv_pointer
; break;
38 case LTTV_STRING
: va
.v_string
= &v
->dv_string
; break;
39 case LTTV_GOBJECT
: va
.v_gobject
= &v
->dv_gobject
; break;
45 AttributeValue
init_value(LttvAttributeType t
)
50 case LTTV_INT
: v
.dv_int
= 0; break;
51 case LTTV_UINT
: v
.dv_uint
= 0; break;
52 case LTTV_LONG
: v
.dv_long
= 0; break;
53 case LTTV_ULONG
: v
.dv_ulong
= 0; break;
54 case LTTV_FLOAT
: v
.dv_float
= 0; break;
55 case LTTV_DOUBLE
: v
.dv_double
= 0; break;
56 case LTTV_TIME
: v
.dv_time
.tv_sec
= 0; v
.dv_time
.tv_nsec
= 0; break;
57 case LTTV_POINTER
: v
.dv_pointer
= NULL
; break;
58 case LTTV_STRING
: v
.dv_string
= NULL
; break;
59 case LTTV_GOBJECT
: v
.dv_gobject
= NULL
; break;
66 lttv_attribute_get_number(LttvAttribute
*self
)
68 return self
->attributes
->len
;
73 lttv_attribute_named(LttvAttribute
*self
, gboolean
*homogeneous
)
81 lttv_attribute_get(LttvAttribute
*self
, unsigned i
, LttvAttributeName
*name
,
82 LttvAttributeValue
*v
)
86 a
= &g_array_index(self
->attributes
, Attribute
, i
);
88 *v
= address_of_value(a
->type
, &(a
->value
));
94 lttv_attribute_get_by_name(LttvAttribute
*self
, LttvAttributeName name
,
95 LttvAttributeValue
*v
)
103 p
= g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
104 if(p
== NULL
) return LTTV_NONE
;
106 i
= GPOINTER_TO_UINT(p
);
108 a
= &g_array_index(self
->attributes
, Attribute
, i
);
109 *v
= address_of_value(a
->type
, &(a
->value
));
115 lttv_attribute_add(LttvAttribute
*self
, LttvAttributeName name
,
122 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
123 if(i
!= 0) g_error("duplicate entry in attribute table");
127 a
.value
= init_value(t
);
128 g_array_append_val(self
->attributes
, a
);
129 i
= self
->attributes
->len
- 1;
130 pa
= &g_array_index(self
->attributes
, Attribute
, i
);
131 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(name
),
132 GUINT_TO_POINTER(i
+ 1));
133 return address_of_value(t
, &(pa
->value
));
137 /* Remove an attribute */
140 lttv_attribute_remove(LttvAttribute
*self
, unsigned i
)
144 a
= &g_array_index(self
->attributes
, Attribute
, i
);
146 /* Remove the array element and its entry in the name index */
148 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
149 g_array_remove_index_fast(self
->attributes
, i
);
151 /* The element used to replace the removed element has its index entry
152 all wrong now. Reinsert it with its new position. */
154 if(self
->attributes
->len
!= i
){
155 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
156 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(a
->name
), GUINT_TO_POINTER(i
+ 1));
161 lttv_attribute_remove_by_name(LttvAttribute
*self
, LttvAttributeName name
)
165 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
166 if(i
== 0) g_error("remove by name non existent attribute");
168 lttv_attribute_remove(self
, i
- 1);
171 /* Create an empty iattribute object and add it as an attribute under the
172 specified name, or return an existing iattribute attribute. If an
173 attribute of that name already exists but is not a GObject supporting the
174 iattribute interface, return NULL. */
177 lttv_attribute_create_subdir(LttvAttribute
*self
, LttvAttributeName name
)
185 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
187 a
= g_array_index(self
->attributes
, Attribute
, i
- 1);
188 if(a
.type
== LTTV_GOBJECT
&& LTTV_IS_IATTRIBUTE(a
.value
.dv_gobject
)) {
189 return LTTV_IATTRIBUTE(a
.value
.dv_gobject
);
193 new = g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
194 *(lttv_attribute_add(self
, name
, LTTV_GOBJECT
).v_gobject
) = G_OBJECT(new);
195 return (LttvIAttribute
*)new;
199 lttv_attribute_find(LttvAttribute
*self
, LttvAttributeName name
,
200 LttvAttributeType t
, LttvAttributeValue
*v
)
206 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
208 a
= &g_array_index(self
->attributes
, Attribute
, i
- 1);
209 if(a
->type
!= t
) return FALSE
;
210 *v
= address_of_value(t
, &(a
->value
));
214 *v
= lttv_attribute_add(self
, name
, t
);
220 attribute_interface_init (gpointer g_iface
, gpointer iface_data
)
222 LttvIAttributeClass
*klass
= (LttvIAttributeClass
*)g_iface
;
224 klass
->get_number
= (unsigned int (*) (LttvIAttribute
*self
))
225 lttv_attribute_get_number
;
227 klass
->named
= (gboolean (*) (LttvIAttribute
*self
, gboolean
*homogeneous
))
228 lttv_attribute_named
;
230 klass
->get
= (LttvAttributeType (*) (LttvIAttribute
*self
, unsigned i
,
231 LttvAttributeName
*name
, LttvAttributeValue
*v
)) lttv_attribute_get
;
233 klass
->get_by_name
= (LttvAttributeType (*) (LttvIAttribute
*self
,
234 LttvAttributeName name
, LttvAttributeValue
*v
))
235 lttv_attribute_get_by_name
;
237 klass
->add
= (LttvAttributeValue (*) (LttvIAttribute
*self
,
238 LttvAttributeName name
, LttvAttributeType t
)) lttv_attribute_add
;
240 klass
->remove
= (void (*) (LttvIAttribute
*self
, unsigned i
))
241 lttv_attribute_remove
;
243 klass
->remove_by_name
= (void (*) (LttvIAttribute
*self
,
244 LttvAttributeName name
)) lttv_attribute_remove_by_name
;
246 klass
->create_subdir
= (LttvIAttribute
* (*) (LttvIAttribute
*self
,
247 LttvAttributeName name
)) lttv_attribute_create_subdir
;
252 attribute_instance_init (GTypeInstance
*instance
, gpointer g_class
)
254 LttvAttribute
*self
= (LttvAttribute
*)instance
;
255 self
->names
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
256 self
->attributes
= g_array_new(FALSE
, FALSE
, sizeof(Attribute
));
261 attribute_finalize (LttvAttribute
*self
)
263 g_hash_table_destroy(self
->names
);
264 g_array_free(self
->attributes
, TRUE
);
265 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_GET_CLASS(self
)))->finalize(G_OBJECT(self
));
270 attribute_class_init (LttvAttributeClass
*klass
)
272 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
274 gobject_class
->finalize
= (void (*)(GObject
*self
))attribute_finalize
;
278 lttv_attribute_get_type (void)
280 static GType type
= 0;
282 static const GTypeInfo info
= {
283 sizeof (LttvAttributeClass
),
284 NULL
, /* base_init */
285 NULL
, /* base_finalize */
286 (GClassInitFunc
) attribute_class_init
, /* class_init */
287 NULL
, /* class_finalize */
288 NULL
, /* class_data */
289 sizeof (LttvAttribute
),
291 (GInstanceInitFunc
) attribute_instance_init
/* instance_init */
294 static const GInterfaceInfo iattribute_info
= {
295 (GInterfaceInitFunc
) attribute_interface_init
, /* interface_init */
296 NULL
, /* interface_finalize */
297 NULL
/* interface_data */
300 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvAttributeType", &info
,
302 g_type_add_interface_static (type
, LTTV_IATTRIBUTE_TYPE
, &iattribute_info
);