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 g_hash_table_remove(self
->names
, GUINT_TO_POINTER(a
->name
));
155 g_hash_table_insert(self
->names
, GUINT_TO_POINTER(a
->name
), GUINT_TO_POINTER(i
+ 1));
159 lttv_attribute_remove_by_name(LttvAttribute
*self
, LttvAttributeName name
)
163 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
164 if(i
== 0) g_error("remove by name non existent attribute");
166 lttv_attribute_remove(self
, i
- 1);
169 /* Create an empty iattribute object and add it as an attribute under the
170 specified name, or return an existing iattribute attribute. If an
171 attribute of that name already exists but is not a GObject supporting the
172 iattribute interface, return NULL. */
175 lttv_attribute_create_subdir(LttvAttribute
*self
, LttvAttributeName name
)
183 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
185 a
= g_array_index(self
->attributes
, Attribute
, i
- 1);
186 if(a
.type
== LTTV_GOBJECT
&& LTTV_IS_IATTRIBUTE(a
.value
.dv_gobject
)) {
187 return LTTV_IATTRIBUTE(a
.value
.dv_gobject
);
191 new = g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
192 *(lttv_attribute_add(self
, name
, LTTV_GOBJECT
).v_gobject
) = G_OBJECT(new);
193 return (LttvIAttribute
*)new;
197 lttv_attribute_find(LttvAttribute
*self
, LttvAttributeName name
,
198 LttvAttributeType t
, LttvAttributeValue
*v
)
204 i
= (unsigned)g_hash_table_lookup(self
->names
, GUINT_TO_POINTER(name
));
206 a
= &g_array_index(self
->attributes
, Attribute
, i
- 1);
207 if(a
->type
!= t
) return FALSE
;
208 *v
= address_of_value(t
, &(a
->value
));
212 *v
= lttv_attribute_add(self
, name
, t
);
218 attribute_interface_init (gpointer g_iface
, gpointer iface_data
)
220 LttvIAttributeClass
*klass
= (LttvIAttributeClass
*)g_iface
;
222 klass
->get_number
= (unsigned int (*) (LttvIAttribute
*self
))
223 lttv_attribute_get_number
;
225 klass
->named
= (gboolean (*) (LttvIAttribute
*self
, gboolean
*homogeneous
))
226 lttv_attribute_named
;
228 klass
->get
= (LttvAttributeType (*) (LttvIAttribute
*self
, unsigned i
,
229 LttvAttributeName
*name
, LttvAttributeValue
*v
)) lttv_attribute_get
;
231 klass
->get_by_name
= (LttvAttributeType (*) (LttvIAttribute
*self
,
232 LttvAttributeName name
, LttvAttributeValue
*v
))
233 lttv_attribute_get_by_name
;
235 klass
->add
= (LttvAttributeValue (*) (LttvIAttribute
*self
,
236 LttvAttributeName name
, LttvAttributeType t
)) lttv_attribute_add
;
238 klass
->remove
= (void (*) (LttvIAttribute
*self
, unsigned i
))
239 lttv_attribute_remove
;
241 klass
->remove_by_name
= (void (*) (LttvIAttribute
*self
,
242 LttvAttributeName name
)) lttv_attribute_remove_by_name
;
244 klass
->create_subdir
= (LttvIAttribute
* (*) (LttvIAttribute
*self
,
245 LttvAttributeName name
)) lttv_attribute_create_subdir
;
250 attribute_instance_init (GTypeInstance
*instance
, gpointer g_class
)
252 LttvAttribute
*self
= (LttvAttribute
*)instance
;
253 self
->names
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
254 self
->attributes
= g_array_new(FALSE
, FALSE
, sizeof(Attribute
));
259 attribute_finalize (LttvAttribute
*self
)
261 g_hash_table_destroy(self
->names
);
262 g_array_free(self
->attributes
, TRUE
);
263 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_GET_CLASS(self
)))->finalize(G_OBJECT(self
));
268 attribute_class_init (LttvAttributeClass
*klass
)
270 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
272 gobject_class
->finalize
= (void (*)(GObject
*self
))attribute_finalize
;
276 lttv_attribute_get_type (void)
278 static GType type
= 0;
280 static const GTypeInfo info
= {
281 sizeof (LttvAttributeClass
),
282 NULL
, /* base_init */
283 NULL
, /* base_finalize */
284 (GClassInitFunc
) attribute_class_init
, /* class_init */
285 NULL
, /* class_finalize */
286 NULL
, /* class_data */
287 sizeof (LttvAttribute
),
289 (GInstanceInitFunc
) attribute_instance_init
/* instance_init */
292 static const GInterfaceInfo iattribute_info
= {
293 (GInterfaceInitFunc
) attribute_interface_init
, /* interface_init */
294 NULL
, /* interface_finalize */
295 NULL
/* interface_data */
298 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvAttributeType", &info
,
300 g_type_add_interface_static (type
, LTTV_IATTRIBUTE_TYPE
, &iattribute_info
);