Add state saving functions and update processTrace accordingly.
[lttv.git] / ltt / branches / poly / lttv / attribute.c
1
2 #include <lttv/attribute.h>
3 #include <ltt/ltt.h>
4
5 typedef union _AttributeValue {
6 int dv_int;
7 unsigned dv_uint;
8 long dv_long;
9 unsigned long dv_ulong;
10 float dv_float;
11 double dv_double;
12 LttTime dv_time;
13 gpointer dv_pointer;
14 char *dv_string;
15 GObject *dv_gobject;
16 } AttributeValue;
17
18
19 typedef struct _Attribute {
20 LttvAttributeName name;
21 LttvAttributeType type;
22 AttributeValue value;
23 } Attribute;
24
25
26 LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
27 {
28 LttvAttributeValue va;
29
30 switch(t) {
31 case LTTV_INT: va.v_int = &v->dv_int; break;
32 case LTTV_UINT: va.v_uint = &v->dv_uint; break;
33 case LTTV_LONG: va.v_long = &v->dv_long; break;
34 case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break;
35 case LTTV_FLOAT: va.v_float = &v->dv_float; break;
36 case LTTV_DOUBLE: va.v_double = &v->dv_double; break;
37 case LTTV_TIME: va.v_time = &v->dv_time; break;
38 case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break;
39 case LTTV_STRING: va.v_string = &v->dv_string; break;
40 case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break;
41 }
42 return va;
43 }
44
45
46 AttributeValue init_value(LttvAttributeType t)
47 {
48 AttributeValue v;
49
50 switch(t) {
51 case LTTV_INT: v.dv_int = 0; break;
52 case LTTV_UINT: v.dv_uint = 0; break;
53 case LTTV_LONG: v.dv_long = 0; break;
54 case LTTV_ULONG: v.dv_ulong = 0; break;
55 case LTTV_FLOAT: v.dv_float = 0; break;
56 case LTTV_DOUBLE: v.dv_double = 0; break;
57 case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break;
58 case LTTV_POINTER: v.dv_pointer = NULL; break;
59 case LTTV_STRING: v.dv_string = NULL; break;
60 case LTTV_GOBJECT: v.dv_gobject = NULL; break;
61 }
62 return v;
63 }
64
65
66 unsigned int
67 lttv_attribute_get_number(LttvAttribute *self)
68 {
69 return self->attributes->len;
70 }
71
72
73 gboolean
74 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
75 {
76 *homogeneous = FALSE;
77 return TRUE;
78 }
79
80
81 LttvAttributeType
82 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
83 LttvAttributeValue *v)
84 {
85 Attribute *a;
86
87 a = &g_array_index(self->attributes, Attribute, i);
88 *name = a->name;
89 *v = address_of_value(a->type, &(a->value));
90 return a->type;
91 }
92
93
94 LttvAttributeType
95 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
96 LttvAttributeValue *v)
97 {
98 Attribute *a;
99
100 unsigned i;
101
102 gpointer p;
103
104 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
105 if(p == NULL) return LTTV_NONE;
106
107 i = GPOINTER_TO_UINT(p);
108 i--;
109 a = &g_array_index(self->attributes, Attribute, i);
110 *v = address_of_value(a->type, &(a->value));
111 return a->type;
112 }
113
114
115 LttvAttributeValue
116 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
117 LttvAttributeType t)
118 {
119 unsigned i;
120
121 Attribute a, *pa;
122
123 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
124 if(i != 0) g_error("duplicate entry in attribute table");
125
126 a.name = name;
127 a.type = t;
128 a.value = init_value(t);
129 g_array_append_val(self->attributes, a);
130 i = self->attributes->len - 1;
131 pa = &g_array_index(self->attributes, Attribute, i);
132 g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
133 GUINT_TO_POINTER(i + 1));
134 return address_of_value(t, &(pa->value));
135 }
136
137
138 /* Remove an attribute */
139
140 void
141 lttv_attribute_remove(LttvAttribute *self, unsigned i)
142 {
143 Attribute *a;
144
145 a = &g_array_index(self->attributes, Attribute, i);
146
147 /* Remove the array element and its entry in the name index */
148
149 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
150 g_array_remove_index_fast(self->attributes, i);
151
152 /* The element used to replace the removed element has its index entry
153 all wrong now. Reinsert it with its new position. */
154
155 if(self->attributes->len != i){
156 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
157 g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
158 }
159 }
160
161 void
162 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
163 {
164 unsigned i;
165
166 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
167 if(i == 0) g_error("remove by name non existent attribute");
168
169 lttv_attribute_remove(self, i - 1);
170 }
171
172 /* Create an empty iattribute object and add it as an attribute under the
173 specified name, or return an existing iattribute attribute. If an
174 attribute of that name already exists but is not a GObject supporting the
175 iattribute interface, return NULL. */
176
177 /*CHECK*/LttvAttribute*
178 lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
179 {
180 unsigned i;
181
182 Attribute a;
183
184 LttvAttribute *new;
185
186 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
187 if(i != 0) {
188 a = g_array_index(self->attributes, Attribute, i - 1);
189 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
190 return LTTV_ATTRIBUTE(a.value.dv_gobject);
191 }
192 else return NULL;
193 }
194 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
195 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
196 return (LttvAttribute *)new;
197 }
198
199 gboolean
200 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
201 LttvAttributeType t, LttvAttributeValue *v)
202 {
203 unsigned i;
204
205 Attribute *a;
206
207 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
208 if(i != 0) {
209 a = &g_array_index(self->attributes, Attribute, i - 1);
210 if(a->type != t) return FALSE;
211 *v = address_of_value(t, &(a->value));
212 return TRUE;
213 }
214
215 *v = lttv_attribute_add(self, name, t);
216 return TRUE;
217 }
218
219
220 void lttv_attribute_recursive_free(LttvAttribute *self)
221 {
222 int i, nb;
223
224 Attribute *a;
225
226 nb = self->attributes->len;
227
228 for(i = 0 ; i < nb ; i++) {
229 a = &g_array_index(self->attributes, Attribute, i);
230 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
231 lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
232 }
233 }
234 g_object_unref(self);
235 }
236
237
238 void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
239 {
240 int i, nb;
241
242 Attribute *a;
243
244 LttvAttributeValue value;
245
246 nb = src->attributes->len;
247
248 for(i = 0 ; i < nb ; i++) {
249 a = &g_array_index(src->attributes, Attribute, i);
250 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
251 lttv_attribute_recursive_add(
252 /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
253 (LttvAttribute *)(a->value.dv_gobject));
254 }
255 else {
256 g_assert(lttv_attribute_find(dest, a->name, a->type, &value));
257 switch(a->type) {
258 case LTTV_INT:
259 *value.v_int += a->value.dv_int;
260 break;
261 case LTTV_UINT:
262 *value.v_uint += a->value.dv_uint;
263 break;
264 case LTTV_LONG:
265 *value.v_long += a->value.dv_long;
266 break;
267 case LTTV_ULONG:
268 *value.v_ulong += a->value.dv_ulong;
269 break;
270 case LTTV_FLOAT:
271 *value.v_float += a->value.dv_float;
272 break;
273 case LTTV_DOUBLE:
274 *value.v_double += a->value.dv_double;
275 break;
276 case LTTV_TIME:
277 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
278 break;
279 case LTTV_POINTER:
280 break;
281 case LTTV_STRING:
282 break;
283 case LTTV_GOBJECT:
284 break;
285 case LTTV_NONE:
286 break;
287 }
288 }
289 }
290 }
291
292
293 static void
294 attribute_interface_init (gpointer g_iface, gpointer iface_data)
295 {
296 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
297
298 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
299 lttv_attribute_get_number;
300
301 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
302 lttv_attribute_named;
303
304 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
305 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
306
307 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
308 LttvAttributeName name, LttvAttributeValue *v))
309 lttv_attribute_get_by_name;
310
311 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
312 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
313
314 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
315 lttv_attribute_remove;
316
317 klass->remove_by_name = (void (*) (LttvIAttribute *self,
318 LttvAttributeName name)) lttv_attribute_remove_by_name;
319
320 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
321 LttvAttributeName name)) lttv_attribute_find_subdir;
322 }
323
324
325 static void
326 attribute_instance_init (GTypeInstance *instance, gpointer g_class)
327 {
328 LttvAttribute *self = (LttvAttribute *)instance;
329 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
330 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
331 }
332
333
334 static void
335 attribute_finalize (LttvAttribute *self)
336 {
337 g_hash_table_destroy(self->names);
338 g_critical("attribute_finalize()");
339 g_array_free(self->attributes, TRUE);
340 G_OBJECT_CLASS(g_type_class_peek_parent(
341 g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
342 }
343
344
345 static void
346 attribute_class_init (LttvAttributeClass *klass)
347 {
348 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
349
350 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
351 }
352
353 GType
354 lttv_attribute_get_type (void)
355 {
356 static GType type = 0;
357 if (type == 0) {
358 static const GTypeInfo info = {
359 sizeof (LttvAttributeClass),
360 NULL, /* base_init */
361 NULL, /* base_finalize */
362 (GClassInitFunc) attribute_class_init, /* class_init */
363 NULL, /* class_finalize */
364 NULL, /* class_data */
365 sizeof (LttvAttribute),
366 0, /* n_preallocs */
367 (GInstanceInitFunc) attribute_instance_init /* instance_init */
368 };
369
370 static const GInterfaceInfo iattribute_info = {
371 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
372 NULL, /* interface_finalize */
373 NULL /* interface_data */
374 };
375
376 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
377 0);
378 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
379 }
380 return type;
381 }
382
383
This page took 0.035951 seconds and 4 git commands to generate.