git-svn-id: http://ltt.polymtl.ca/svn@289 04897980-b3bd-0310-b5e0-8ef037075253
[lttv.git] / ltt / branches / poly / lttv / attribute.c
CommitLineData
dc877563 1
fcdf0ec2 2#include <lttv/attribute.h>
f32847a1 3
dc877563 4typedef union _AttributeValue {
5 int dv_int;
6 unsigned dv_uint;
7 long dv_long;
8 unsigned long dv_ulong;
9 float dv_float;
10 double dv_double;
ffd54a90 11 LttvTime dv_time;
dc877563 12 gpointer dv_pointer;
13 char *dv_string;
ffd54a90 14 GObject *dv_gobject;
dc877563 15} AttributeValue;
16
17
18typedef struct _Attribute {
19 LttvAttributeName name;
20 LttvAttributeType type;
21 AttributeValue value;
22} Attribute;
23
24
ffd54a90 25LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
dc877563 26{
ffd54a90 27 LttvAttributeValue va;
28
29 switch(t) {
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;
40 }
41 return va;
42}
dc877563 43
dc877563 44
ffd54a90 45AttributeValue init_value(LttvAttributeType t)
46{
47 AttributeValue v;
48
49 switch(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;
dc877563 60 }
ffd54a90 61 return v;
f32847a1 62}
63
64
dc877563 65unsigned int
66lttv_attribute_get_number(LttvAttribute *self)
67{
68 return self->attributes->len;
f32847a1 69}
70
71
dc877563 72gboolean
73lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
74{
75 *homogeneous = FALSE;
76 return TRUE;
f32847a1 77}
78
79
dc877563 80LttvAttributeType
81lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
82 LttvAttributeValue *v)
83{
84 Attribute *a;
f32847a1 85
dc877563 86 a = &g_array_index(self->attributes, Attribute, i);
87 *name = a->name;
ffd54a90 88 *v = address_of_value(a->type, &(a->value));
dc877563 89 return a->type;
f32847a1 90}
91
92
dc877563 93LttvAttributeType
94lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
95 LttvAttributeValue *v)
96{
97 Attribute *a;
f32847a1 98
dc877563 99 unsigned i;
f32847a1 100
ffd54a90 101 gpointer p;
102
103 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
104 if(p == NULL) return LTTV_NONE;
f32847a1 105
ba576a78 106 i = GPOINTER_TO_UINT(p);
dc877563 107 i--;
108 a = &g_array_index(self->attributes, Attribute, i);
ffd54a90 109 *v = address_of_value(a->type, &(a->value));
dc877563 110 return a->type;
f32847a1 111}
112
f32847a1 113
dc877563 114LttvAttributeValue
115lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
116 LttvAttributeType t)
117{
118 unsigned i;
f32847a1 119
dc877563 120 Attribute a, *pa;
f32847a1 121
ffd54a90 122 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 123 if(i != 0) g_error("duplicate entry in attribute table");
f32847a1 124
ffd54a90 125 a.name = name;
126 a.type = t;
127 a.value = init_value(t);
dc877563 128 g_array_append_val(self->attributes, a);
129 i = self->attributes->len - 1;
ffd54a90 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));
f32847a1 134}
135
136
dc877563 137/* Remove an attribute */
f32847a1 138
dc877563 139void
140lttv_attribute_remove(LttvAttribute *self, unsigned i)
f32847a1 141{
dc877563 142 Attribute *a;
f32847a1 143
dc877563 144 a = &g_array_index(self->attributes, Attribute, i);
f32847a1 145
dc877563 146 /* Remove the array element and its entry in the name index */
f32847a1 147
ffd54a90 148 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
dc877563 149 g_array_remove_index_fast(self->attributes, i);
f32847a1 150
dc877563 151 /* The element used to replace the removed element has its index entry
152 all wrong now. Reinsert it with its new position. */
f32847a1 153
c6bc9cb9 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));
157 }
f32847a1 158}
159
dc877563 160void
161lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
162{
163 unsigned i;
f32847a1 164
ffd54a90 165 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 166 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 167
dc877563 168 lttv_attribute_remove(self, i - 1);
f32847a1 169}
170
dc877563 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. */
f32847a1 175
dc877563 176LttvIAttribute*
177lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 178{
dc877563 179 unsigned i;
f32847a1 180
dc877563 181 Attribute a;
f32847a1 182
dc877563 183 LttvAttribute *new;
f32847a1 184
ffd54a90 185 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 186 if(i != 0) {
187 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 188 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
189 return LTTV_IATTRIBUTE(a.value.dv_gobject);
dc877563 190 }
191 else return NULL;
f32847a1 192 }
ffd54a90 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;
f32847a1 196}
197
dc877563 198gboolean
199lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
200 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 201{
dc877563 202 unsigned i;
f32847a1 203
dc877563 204 Attribute *a;
f32847a1 205
ffd54a90 206 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 207 if(i != 0) {
208 a = &g_array_index(self->attributes, Attribute, i - 1);
209 if(a->type != t) return FALSE;
ffd54a90 210 *v = address_of_value(t, &(a->value));
dc877563 211 return TRUE;
212 }
f32847a1 213
dc877563 214 *v = lttv_attribute_add(self, name, t);
215 return TRUE;
f32847a1 216}
217
f32847a1 218
dc877563 219static void
220attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 221{
dc877563 222 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 223
dc877563 224 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
225 lttv_attribute_get_number;
f32847a1 226
dc877563 227 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
228 lttv_attribute_named;
f32847a1 229
dc877563 230 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
231 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 232
dc877563 233 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
234 LttvAttributeName name, LttvAttributeValue *v))
235 lttv_attribute_get_by_name;
f32847a1 236
dc877563 237 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
238 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 239
dc877563 240 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
241 lttv_attribute_remove;
f32847a1 242
dc877563 243 klass->remove_by_name = (void (*) (LttvIAttribute *self,
244 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 245
dc877563 246 klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
247 LttvAttributeName name)) lttv_attribute_create_subdir;
f32847a1 248}
249
250
dc877563 251static void
252attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 253{
dc877563 254 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 255 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
256 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 257}
258
f32847a1 259
dc877563 260static void
261attribute_finalize (LttvAttribute *self)
f32847a1 262{
ba576a78 263 g_hash_table_destroy(self->names);
dc877563 264 g_array_free(self->attributes, TRUE);
ffd54a90 265 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_GET_CLASS(self)))->finalize(G_OBJECT(self));
f32847a1 266}
267
f32847a1 268
dc877563 269static void
270attribute_class_init (LttvAttributeClass *klass)
f32847a1 271{
dc877563 272 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
f32847a1 273
ffd54a90 274 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 275}
276
ffd54a90 277GType
278lttv_attribute_get_type (void)
279{
280 static GType type = 0;
281 if (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),
290 0, /* n_preallocs */
291 (GInstanceInitFunc) attribute_instance_init /* instance_init */
292 };
293
294 static const GInterfaceInfo iattribute_info = {
295 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
296 NULL, /* interface_finalize */
297 NULL /* interface_data */
298 };
299
300 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
301 0);
302 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
303 }
304 return type;
305}
306
307
This page took 0.038501 seconds and 4 git commands to generate.