git-svn-id: http://ltt.polymtl.ca/svn@172 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
ffd54a90 106 i = POINTER_TO_GUINT(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
ffd54a90 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));
f32847a1 156}
157
dc877563 158void
159lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
160{
161 unsigned i;
f32847a1 162
ffd54a90 163 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 164 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 165
dc877563 166 lttv_attribute_remove(self, i - 1);
f32847a1 167}
168
dc877563 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. */
f32847a1 173
dc877563 174LttvIAttribute*
175lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 176{
dc877563 177 unsigned i;
f32847a1 178
dc877563 179 Attribute a;
f32847a1 180
dc877563 181 LttvAttribute *new;
f32847a1 182
ffd54a90 183 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 184 if(i != 0) {
185 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 186 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
187 return LTTV_IATTRIBUTE(a.value.dv_gobject);
dc877563 188 }
189 else return NULL;
f32847a1 190 }
ffd54a90 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;
f32847a1 194}
195
dc877563 196gboolean
197lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
198 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 199{
dc877563 200 unsigned i;
f32847a1 201
dc877563 202 Attribute *a;
f32847a1 203
ffd54a90 204 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 205 if(i != 0) {
206 a = &g_array_index(self->attributes, Attribute, i - 1);
207 if(a->type != t) return FALSE;
ffd54a90 208 *v = address_of_value(t, &(a->value));
dc877563 209 return TRUE;
210 }
f32847a1 211
dc877563 212 *v = lttv_attribute_add(self, name, t);
213 return TRUE;
f32847a1 214}
215
f32847a1 216
dc877563 217static void
218attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 219{
dc877563 220 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 221
dc877563 222 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
223 lttv_attribute_get_number;
f32847a1 224
dc877563 225 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
226 lttv_attribute_named;
f32847a1 227
dc877563 228 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
229 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 230
dc877563 231 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
232 LttvAttributeName name, LttvAttributeValue *v))
233 lttv_attribute_get_by_name;
f32847a1 234
dc877563 235 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
236 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 237
dc877563 238 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
239 lttv_attribute_remove;
f32847a1 240
dc877563 241 klass->remove_by_name = (void (*) (LttvIAttribute *self,
242 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 243
dc877563 244 klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
245 LttvAttributeName name)) lttv_attribute_create_subdir;
f32847a1 246}
247
248
dc877563 249static void
250attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 251{
dc877563 252 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 253 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
254 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 255}
256
f32847a1 257
dc877563 258static void
259attribute_finalize (LttvAttribute *self)
f32847a1 260{
dc877563 261 g_hash_table_free(self->names);
262 g_array_free(self->attributes, TRUE);
ffd54a90 263 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_GET_CLASS(self)))->finalize(G_OBJECT(self));
f32847a1 264}
265
f32847a1 266
dc877563 267static void
268attribute_class_init (LttvAttributeClass *klass)
f32847a1 269{
dc877563 270 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
f32847a1 271
ffd54a90 272 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 273}
274
ffd54a90 275GType
276lttv_attribute_get_type (void)
277{
278 static GType type = 0;
279 if (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),
288 0, /* n_preallocs */
289 (GInstanceInitFunc) attribute_instance_init /* instance_init */
290 };
291
292 static const GInterfaceInfo iattribute_info = {
293 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
294 NULL, /* interface_finalize */
295 NULL /* interface_data */
296 };
297
298 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
299 0);
300 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
301 }
302 return type;
303}
304
305
This page took 0.035895 seconds and 4 git commands to generate.