use realpath to get the absolute pathname, fixes some forgotten cases, especially...
[lttv.git] / ltt / branches / poly / lttv / main / attribute.c
CommitLineData
9c312311 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 */
dc877563 18
fcdf0ec2 19#include <lttv/attribute.h>
b445142a 20#include <ltt/ltt.h>
f32847a1 21
dc877563 22typedef 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;
308711e5 29 LttTime dv_time;
dc877563 30 gpointer dv_pointer;
31 char *dv_string;
ffd54a90 32 GObject *dv_gobject;
dc877563 33} AttributeValue;
34
35
36typedef struct _Attribute {
37 LttvAttributeName name;
38 LttvAttributeType type;
39 AttributeValue value;
40} Attribute;
41
42
ffd54a90 43LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
dc877563 44{
ffd54a90 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}
dc877563 61
dc877563 62
ffd54a90 63AttributeValue 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;
dc877563 78 }
ffd54a90 79 return v;
f32847a1 80}
81
82
dc877563 83unsigned int
84lttv_attribute_get_number(LttvAttribute *self)
85{
86 return self->attributes->len;
f32847a1 87}
88
89
dc877563 90gboolean
91lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
92{
93 *homogeneous = FALSE;
94 return TRUE;
f32847a1 95}
96
97
dc877563 98LttvAttributeType
99lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
100 LttvAttributeValue *v)
101{
102 Attribute *a;
f32847a1 103
dc877563 104 a = &g_array_index(self->attributes, Attribute, i);
105 *name = a->name;
ffd54a90 106 *v = address_of_value(a->type, &(a->value));
dc877563 107 return a->type;
f32847a1 108}
109
110
dc877563 111LttvAttributeType
112lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
113 LttvAttributeValue *v)
114{
115 Attribute *a;
f32847a1 116
dc877563 117 unsigned i;
f32847a1 118
ffd54a90 119 gpointer p;
120
121 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
122 if(p == NULL) return LTTV_NONE;
f32847a1 123
ba576a78 124 i = GPOINTER_TO_UINT(p);
dc877563 125 i--;
126 a = &g_array_index(self->attributes, Attribute, i);
ffd54a90 127 *v = address_of_value(a->type, &(a->value));
dc877563 128 return a->type;
f32847a1 129}
130
f32847a1 131
dc877563 132LttvAttributeValue
133lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
134 LttvAttributeType t)
135{
136 unsigned i;
f32847a1 137
dc877563 138 Attribute a, *pa;
f32847a1 139
ffd54a90 140 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 141 if(i != 0) g_error("duplicate entry in attribute table");
f32847a1 142
ffd54a90 143 a.name = name;
144 a.type = t;
145 a.value = init_value(t);
dc877563 146 g_array_append_val(self->attributes, a);
147 i = self->attributes->len - 1;
ffd54a90 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));
f32847a1 152}
153
154
dc877563 155/* Remove an attribute */
f32847a1 156
dc877563 157void
158lttv_attribute_remove(LttvAttribute *self, unsigned i)
f32847a1 159{
dc877563 160 Attribute *a;
f32847a1 161
dc877563 162 a = &g_array_index(self->attributes, Attribute, i);
f32847a1 163
dc877563 164 /* Remove the array element and its entry in the name index */
f32847a1 165
ffd54a90 166 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
dc877563 167 g_array_remove_index_fast(self->attributes, i);
f32847a1 168
dc877563 169 /* The element used to replace the removed element has its index entry
170 all wrong now. Reinsert it with its new position. */
f32847a1 171
c6bc9cb9 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 }
f32847a1 176}
177
dc877563 178void
179lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
180{
181 unsigned i;
f32847a1 182
ffd54a90 183 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 184 if(i == 0) g_error("remove by name non existent attribute");
f32847a1 185
dc877563 186 lttv_attribute_remove(self, i - 1);
f32847a1 187}
188
dc877563 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. */
f32847a1 193
b445142a 194/*CHECK*/LttvAttribute*
195lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
f32847a1 196{
dc877563 197 unsigned i;
f32847a1 198
dc877563 199 Attribute a;
f32847a1 200
dc877563 201 LttvAttribute *new;
f32847a1 202
ffd54a90 203 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 204 if(i != 0) {
205 a = g_array_index(self->attributes, Attribute, i - 1);
ffd54a90 206 if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
b445142a 207 return LTTV_ATTRIBUTE(a.value.dv_gobject);
dc877563 208 }
209 else return NULL;
f32847a1 210 }
ffd54a90 211 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
212 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
b445142a 213 return (LttvAttribute *)new;
f32847a1 214}
215
dc877563 216gboolean
217lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
218 LttvAttributeType t, LttvAttributeValue *v)
f32847a1 219{
dc877563 220 unsigned i;
f32847a1 221
dc877563 222 Attribute *a;
f32847a1 223
ffd54a90 224 i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
dc877563 225 if(i != 0) {
226 a = &g_array_index(self->attributes, Attribute, i - 1);
227 if(a->type != t) return FALSE;
ffd54a90 228 *v = address_of_value(t, &(a->value));
dc877563 229 return TRUE;
230 }
f32847a1 231
dc877563 232 *v = lttv_attribute_add(self, name, t);
233 return TRUE;
f32847a1 234}
235
f32847a1 236
b445142a 237void 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
255void 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:
308711e5 294 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
b445142a 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
dc877563 310static void
311attribute_interface_init (gpointer g_iface, gpointer iface_data)
f32847a1 312{
dc877563 313 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
f32847a1 314
dc877563 315 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
316 lttv_attribute_get_number;
f32847a1 317
dc877563 318 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
319 lttv_attribute_named;
f32847a1 320
dc877563 321 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
322 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
f32847a1 323
dc877563 324 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
325 LttvAttributeName name, LttvAttributeValue *v))
326 lttv_attribute_get_by_name;
f32847a1 327
dc877563 328 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
329 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
f32847a1 330
dc877563 331 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
332 lttv_attribute_remove;
f32847a1 333
dc877563 334 klass->remove_by_name = (void (*) (LttvIAttribute *self,
335 LttvAttributeName name)) lttv_attribute_remove_by_name;
f32847a1 336
b445142a 337 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
338 LttvAttributeName name)) lttv_attribute_find_subdir;
f32847a1 339}
340
341
dc877563 342static void
343attribute_instance_init (GTypeInstance *instance, gpointer g_class)
f32847a1 344{
dc877563 345 LttvAttribute *self = (LttvAttribute *)instance;
ffd54a90 346 self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
347 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
f32847a1 348}
349
f32847a1 350
dc877563 351static void
352attribute_finalize (LttvAttribute *self)
f32847a1 353{
ba576a78 354 g_hash_table_destroy(self->names);
2a2fa4f0 355 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
dc877563 356 g_array_free(self->attributes, TRUE);
b445142a 357 G_OBJECT_CLASS(g_type_class_peek_parent(
358 g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
f32847a1 359}
360
f32847a1 361
dc877563 362static void
363attribute_class_init (LttvAttributeClass *klass)
f32847a1 364{
dc877563 365 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
f32847a1 366
ffd54a90 367 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
f32847a1 368}
369
ffd54a90 370GType
371lttv_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.0455 seconds and 4 git commands to generate.