2 #include <lttv/attribute.h>
4 typedef union _AttributeValue
{
8 unsigned long dv_ulong
;
18 typedef struct _Attribute
{
19 LttvAttributeName name
;
20 LttvAttributeType type
;
26 lttv_attribute_get_type (void)
28 static GType type
= 0;
30 static const GTypeInfo info
= {
31 sizeof (LttvAttributeClass
),
33 NULL
, /* base_finalize */
34 attribute_class_init
, /* class_init */
35 NULL
, /* class_finalize */
36 NULL
, /* class_data */
37 sizeof (LttvAttribute
),
39 attribute_instance_init
/* instance_init */
42 static const GInterfaceInfo iattribute_info
= {
43 (GInterfaceInitFunc
) attribute_interface_init
, /* interface_init */
44 NULL
, /* interface_finalize */
45 NULL
/* interface_data */
48 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvAttributeType", &info
,
50 g_type_add_interface_static (type
, LTTV_IATTRIBUTE_TYPE
, &iattribute_info
);
57 lttv_attribute_get_number(LttvAttribute
*self
)
59 return self
->attributes
->len
;
64 lttv_attribute_named(LttvAttribute
*self
, gboolean
*homogeneous
)
72 lttv_attribute_get(LttvAttribute
*self
, unsigned i
, LttvAttributeName
*name
,
73 LttvAttributeValue
*v
)
77 a
= &g_array_index(self
->attributes
, Attribute
, i
);
79 *v
= address_of_value(a
->type
, a
->value
);
85 lttv_attribute_get_by_name(LttvAttribute
*self
, LttvAttributeName name
,
86 LttvAttributeValue
*v
)
92 i
= (unsigned)g_hash_table_lookup(self
->names
, (gconstpointer
)name
);
93 if(i
== 0) return LTTV_NONE
;
96 a
= &g_array_index(self
->attributes
, Attribute
, i
);
97 *v
= address_of_value(a
->type
, a
->value
);
103 lttv_attribute_add(LttvAttribute
*self
, LttvAttributeName name
,
110 i
= (unsigned)g_hash_table_lookup(self
->names
, (gconstpointer
)name
);
111 if(i
!= 0) g_error("duplicate entry in attribute table");
115 a
->value
= init_value(t
);
116 g_array_append_val(self
->attributes
, a
);
117 i
= self
->attributes
->len
- 1;
118 pa
= &g_array_index(self
->attributes
, Attribute
, i
)
119 g_hash_table_insert(self
->names
, (gconstpointer
)name
, (gconstpointer
)i
+ 1);
120 return address_of_value(pa
->value
, t
);
124 /* Remove an attribute */
127 lttv_attribute_remove(LttvAttribute
*self
, unsigned i
)
131 a
= &g_array_index(self
->attributes
, Attribute
, i
);
133 /* Remove the array element and its entry in the name index */
135 g_hash_table_remove(self
->names
, (gconspointer
)a
->name
);
136 g_array_remove_index_fast(self
->attributes
, i
);
138 /* The element used to replace the removed element has its index entry
139 all wrong now. Reinsert it with its new position. */
141 g_hash_table_remove(self
->names
, (gconstpointer
)a
->name
);
142 g_hash_table_insert(self
->names
, (gconstpointer
)a
->name
, i
+ 1);
146 lttv_attribute_remove_by_name(LttvAttribute
*self
, LttvAttributeName name
)
150 i
= (unsigned)g_hash_table_lookup(self
->names
, (gconstpointer
)name
);
151 if(i
== 0) g_error("remove by name non existent attribute");
153 lttv_attribute_remove(self
, i
- 1);
156 /* Create an empty iattribute object and add it as an attribute under the
157 specified name, or return an existing iattribute attribute. If an
158 attribute of that name already exists but is not a GObject supporting the
159 iattribute interface, return NULL. */
162 lttv_attribute_create_subdir(LttvAttribute
*self
, LttvAttributeName name
)
170 i
= (unsigned)g_hash_table_lookup(self
->names
, (gconstpointer
)name
);
172 a
= g_array_index(self
->attributes
, Attribute
, i
- 1);
173 if(a
->type
== LTTV_GOBJECT
&& LTTV_IS_IATTRIBUTE(a
->value
->dv_gobject
)) {
174 return LTTV_IATTRIBUTE(a
->value
->dv_gobject
);
178 new = g_object_new(LTTV_ATTRIBUTE_TYPE
);
179 *(lttv_attribute_add(self
, name
, LTTV_GOBJECT
)->v_gobject
) = new;
184 lttv_attribute_find(LttvAttribute
*self
, LttvAttributeName name
,
185 LttvAttributeType t
, LttvAttributeValue
*v
)
191 i
= (unsigned)g_hash_table_lookup(self
->names
, (gconstpointer
)name
);
193 a
= &g_array_index(self
->attributes
, Attribute
, i
- 1);
194 if(a
->type
!= t
) return FALSE
;
195 *v
= address_of_value(a
->value
, t
);
199 *v
= lttv_attribute_add(self
, name
, t
);
205 attribute_interface_init (gpointer g_iface
, gpointer iface_data
)
207 LttvIAttributeClass
*klass
= (LttvIAttributeClass
*)g_iface
;
209 klass
->get_number
= (unsigned int (*) (LttvIAttribute
*self
))
210 lttv_attribute_get_number
;
212 klass
->named
= (gboolean (*) (LttvIAttribute
*self
, gboolean
*homogeneous
))
213 lttv_attribute_named
;
215 klass
->get
= (LttvAttributeType (*) (LttvIAttribute
*self
, unsigned i
,
216 LttvAttributeName
*name
, LttvAttributeValue
*v
)) lttv_attribute_get
;
218 klass
->get_by_name
= (LttvAttributeType (*) (LttvIAttribute
*self
,
219 LttvAttributeName name
, LttvAttributeValue
*v
))
220 lttv_attribute_get_by_name
;
222 klass
->add
= (LttvAttributeValue (*) (LttvIAttribute
*self
,
223 LttvAttributeName name
, LttvAttributeType t
)) lttv_attribute_add
;
225 klass
->remove
= (void (*) (LttvIAttribute
*self
, unsigned i
))
226 lttv_attribute_remove
;
228 klass
->remove_by_name
= (void (*) (LttvIAttribute
*self
,
229 LttvAttributeName name
)) lttv_attribute_remove_by_name
;
231 klass
->create_subdir
= (LttvIAttribute
* (*) (LttvIAttribute
*self
,
232 LttvAttributeName name
)) lttv_attribute_create_subdir
;
237 quark_hash(gconstpointer key
)
244 quark_equal(gconstpointer a
, gconstpointer b
)
250 attribute_instance_init (GTypeInstance
*instance
, gpointer g_class
)
252 LttvAttribute
*self
= (LttvAttribute
*)instance
;
253 self
->names
= g_hash_table_new(quark_hash
, quark_equal
);
254 self
->attributes
= g_array_new(FALSE
, FALSE
,
260 attribute_finalize (LttvAttribute
*self
)
262 g_hash_table_free(self
->names
);
263 g_array_free(self
->attributes
, TRUE
);
264 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_TYPE
))->finalize(self
);
269 attribute_class_init (LttvAttributeClass
*klass
)
271 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
273 gobject_class
->finalize
= attribute_finalize
;