Refine the interactions between the hooks provided by the different modules.
[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 timespec dv_timespec;
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 GType
26 lttv_attribute_get_type (void)
27 {
28 static GType type = 0;
29 if (type == 0) {
30 static const GTypeInfo info = {
31 sizeof (LttvAttributeClass),
32 NULL, /* base_init */
33 NULL, /* base_finalize */
34 attribute_class_init, /* class_init */
35 NULL, /* class_finalize */
36 NULL, /* class_data */
37 sizeof (LttvAttribute),
38 0, /* n_preallocs */
39 attribute_instance_init /* instance_init */
40 };
41
42 static const GInterfaceInfo iattribute_info = {
43 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
44 NULL, /* interface_finalize */
45 NULL /* interface_data */
46 };
47
48 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
49 0);
50 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
51 }
52 return type;
53 }
54
55
56 unsigned int
57 lttv_attribute_get_number(LttvAttribute *self)
58 {
59 return self->attributes->len;
60 }
61
62
63 gboolean
64 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
65 {
66 *homogeneous = FALSE;
67 return TRUE;
68 }
69
70
71 LttvAttributeType
72 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
73 LttvAttributeValue *v)
74 {
75 Attribute *a;
76
77 a = &g_array_index(self->attributes, Attribute, i);
78 *name = a->name;
79 *v = address_of_value(a->type, a->value);
80 return a->type;
81 }
82
83
84 LttvAttributeType
85 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
86 LttvAttributeValue *v)
87 {
88 Attribute *a;
89
90 unsigned i;
91
92 i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
93 if(i == 0) return LTTV_NONE;
94
95 i--;
96 a = &g_array_index(self->attributes, Attribute, i);
97 *v = address_of_value(a->type, a->value);
98 return a->type;
99 }
100
101
102 LttvAttributeValue
103 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
104 LttvAttributeType t)
105 {
106 unsigned i;
107
108 Attribute a, *pa;
109
110 i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
111 if(i != 0) g_error("duplicate entry in attribute table");
112
113 a->name = name;
114 a->type = t;
115 a->value = init_value(t);
116 g_array_append_val(self->attributes, a);
117 i = self->attributes->len - 1;
118 pa = &g_array_index(self->attributes, Attribute, i)
119 g_hash_table_insert(self->names, (gconstpointer)name, (gconstpointer)i + 1);
120 return address_of_value(pa->value, t);
121 }
122
123
124 /* Remove an attribute */
125
126 void
127 lttv_attribute_remove(LttvAttribute *self, unsigned i)
128 {
129 Attribute *a;
130
131 a = &g_array_index(self->attributes, Attribute, i);
132
133 /* Remove the array element and its entry in the name index */
134
135 g_hash_table_remove(self->names, (gconspointer)a->name);
136 g_array_remove_index_fast(self->attributes, i);
137
138 /* The element used to replace the removed element has its index entry
139 all wrong now. Reinsert it with its new position. */
140
141 g_hash_table_remove(self->names, (gconstpointer)a->name);
142 g_hash_table_insert(self->names, (gconstpointer)a->name, i + 1);
143 }
144
145 void
146 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
147 {
148 unsigned i;
149
150 i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
151 if(i == 0) g_error("remove by name non existent attribute");
152
153 lttv_attribute_remove(self, i - 1);
154 }
155
156 /* Create an empty iattribute object and add it as an attribute under the
157 specified name, or return an existing iattribute attribute. If an
158 attribute of that name already exists but is not a GObject supporting the
159 iattribute interface, return NULL. */
160
161 LttvIAttribute*
162 lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name)
163 {
164 unsigned i;
165
166 Attribute a;
167
168 LttvAttribute *new;
169
170 i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
171 if(i != 0) {
172 a = g_array_index(self->attributes, Attribute, i - 1);
173 if(a->type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a->value->dv_gobject)) {
174 return LTTV_IATTRIBUTE(a->value->dv_gobject);
175 }
176 else return NULL;
177 }
178 new = g_object_new(LTTV_ATTRIBUTE_TYPE);
179 *(lttv_attribute_add(self, name, LTTV_GOBJECT)->v_gobject) = new;
180 return new;
181 }
182
183 gboolean
184 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
185 LttvAttributeType t, LttvAttributeValue *v)
186 {
187 unsigned i;
188
189 Attribute *a;
190
191 i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name);
192 if(i != 0) {
193 a = &g_array_index(self->attributes, Attribute, i - 1);
194 if(a->type != t) return FALSE;
195 *v = address_of_value(a->value, t);
196 return TRUE;
197 }
198
199 *v = lttv_attribute_add(self, name, t);
200 return TRUE;
201 }
202
203
204 static void
205 attribute_interface_init (gpointer g_iface, gpointer iface_data)
206 {
207 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
208
209 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
210 lttv_attribute_get_number;
211
212 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
213 lttv_attribute_named;
214
215 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
216 LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
217
218 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
219 LttvAttributeName name, LttvAttributeValue *v))
220 lttv_attribute_get_by_name;
221
222 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
223 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
224
225 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
226 lttv_attribute_remove;
227
228 klass->remove_by_name = (void (*) (LttvIAttribute *self,
229 LttvAttributeName name)) lttv_attribute_remove_by_name;
230
231 klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
232 LttvAttributeName name)) lttv_attribute_create_subdir;
233 }
234
235
236 static guint
237 quark_hash(gconstpointer key)
238 {
239 return (guint)key;
240 }
241
242
243 static gboolean
244 quark_equal(gconstpointer a, gconstpointer b)
245 {
246 return (a == b)
247 }
248
249 static void
250 attribute_instance_init (GTypeInstance *instance, gpointer g_class)
251 {
252 LttvAttribute *self = (LttvAttribute *)instance;
253 self->names = g_hash_table_new(quark_hash, quark_equal);
254 self->attributes = g_array_new(FALSE, FALSE,
255 sizeof(Attribute));
256 }
257
258
259 static void
260 attribute_finalize (LttvAttribute *self)
261 {
262 g_hash_table_free(self->names);
263 g_array_free(self->attributes, TRUE);
264 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_TYPE))->finalize(self);
265 }
266
267
268 static void
269 attribute_class_init (LttvAttributeClass *klass)
270 {
271 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
272
273 gobject_class->finalize = attribute_finalize;
274 }
275
This page took 0.033425 seconds and 4 git commands to generate.