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