git-svn-id: http://ltt.polymtl.ca/svn@179 04897980-b3bd-0310-b5e0-8ef037075253
[lttv.git] / ltt / branches / poly / lttv / attribute.c
1
2 #include <lttv/attribute.h>
3
4 typedef 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;
11 LttvTime dv_time;
12 gpointer dv_pointer;
13 char *dv_string;
14 GObject *dv_gobject;
15 } AttributeValue;
16
17
18 typedef struct _Attribute {
19 LttvAttributeName name;
20 LttvAttributeType type;
21 AttributeValue value;
22 } Attribute;
23
24
25 LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
26 {
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 }
43
44
45 AttributeValue 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;
60 }
61 return v;
62 }
63
64
65 unsigned int
66 lttv_attribute_get_number(LttvAttribute *self)
67 {
68 return self->attributes->len;
69 }
70
71
72 gboolean
73 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
74 {
75 *homogeneous = FALSE;
76 return TRUE;
77 }
78
79
80 LttvAttributeType
81 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
82 LttvAttributeValue *v)
83 {
84 Attribute *a;
85
86 a = &g_array_index(self->attributes, Attribute, i);
87 *name = a->name;
88 *v = address_of_value(a->type, &(a->value));
89 return a->type;
90 }
91
92
93 LttvAttributeType
94 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
95 LttvAttributeValue *v)
96 {
97 Attribute *a;
98
99 unsigned i;
100
101 gpointer p;
102
103 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
104 if(p == NULL) return LTTV_NONE;
105
106 i = GPOINTER_TO_UINT(p);
107 i--;
108 a = &g_array_index(self->attributes, Attribute, i);
109 *v = address_of_value(a->type, &(a->value));
110 return a->type;
111 }
112
113
114 LttvAttributeValue
115 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
116 LttvAttributeType t)
117 {
118 unsigned i;
119
120 Attribute a, *pa;
121
122 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
123 if(i != 0) g_error("duplicate entry in attribute table");
124
125 a.name = name;
126 a.type = t;
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));
134 }
135
136
137 /* Remove an attribute */
138
139 void
140 lttv_attribute_remove(LttvAttribute *self, unsigned i)
141 {
142 Attribute *a;
143
144 a = &g_array_index(self->attributes, Attribute, i);
145
146 /* Remove the array element and its entry in the name index */
147
148 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
149 g_array_remove_index_fast(self->attributes, i);
150
151 /* The element used to replace the removed element has its index entry
152 all wrong now. Reinsert it with its new position. */
153
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 }
158 }
159
160 void
161 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
162 {
163 unsigned i;
164
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");
167
168 lttv_attribute_remove(self, i - 1);
169 }
170
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. */
175
176 LttvIAttribute*
177 lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name)
178 {
179 unsigned i;
180
181 Attribute a;
182
183 LttvAttribute *new;
184
185 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
186 if(i != 0) {
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);
190 }
191 else return NULL;
192 }
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;
196 }
197
198 gboolean
199 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
200 LttvAttributeType t, LttvAttributeValue *v)
201 {
202 unsigned i;
203
204 Attribute *a;
205
206 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
207 if(i != 0) {
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));
211 return TRUE;
212 }
213
214 *v = lttv_attribute_add(self, name, t);
215 return TRUE;
216 }
217
218
219 static void
220 attribute_interface_init (gpointer g_iface, gpointer iface_data)
221 {
222 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
223
224 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
225 lttv_attribute_get_number;
226
227 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
228 lttv_attribute_named;
229
230 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
231 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
232
233 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
234 LttvAttributeName name, LttvAttributeValue *v))
235 lttv_attribute_get_by_name;
236
237 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
238 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
239
240 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
241 lttv_attribute_remove;
242
243 klass->remove_by_name = (void (*) (LttvIAttribute *self,
244 LttvAttributeName name)) lttv_attribute_remove_by_name;
245
246 klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
247 LttvAttributeName name)) lttv_attribute_create_subdir;
248 }
249
250
251 static void
252 attribute_instance_init (GTypeInstance *instance, gpointer g_class)
253 {
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));
257 }
258
259
260 static void
261 attribute_finalize (LttvAttribute *self)
262 {
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));
266 }
267
268
269 static void
270 attribute_class_init (LttvAttributeClass *klass)
271 {
272 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
273
274 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
275 }
276
277 GType
278 lttv_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.035021 seconds and 4 git commands to generate.