Fix tar.gz build by removing legacy include to ltt directory
[lttv.git] / lttv / lttv / 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 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <string.h>
24 #include <lttv/attribute.h>
25 #include <lttv/compiler.h>
26
27 typedef union _AttributeValue {
28 int dv_int;
29 unsigned dv_uint;
30 long dv_long;
31 unsigned long dv_ulong;
32 float dv_float;
33 double dv_double;
34 LttTime dv_time;
35 gpointer dv_pointer;
36 char *dv_string;
37 GObject *dv_gobject;
38 } AttributeValue;
39
40
41 typedef struct _Attribute {
42 LttvAttributeName name;
43 LttvAttributeType type;
44 AttributeValue value;
45 gboolean is_named;
46 } Attribute;
47
48
49 static __inline__ LttvAttributeValue
50 address_of_value(LttvAttributeType t, AttributeValue *v)
51 {
52 LttvAttributeValue va = { NULL }; /* init to NULL for gcc */
53
54 switch(t) {
55 case LTTV_INT: va.v_int = &v->dv_int; break;
56 case LTTV_UINT: va.v_uint = &v->dv_uint; break;
57 case LTTV_LONG: va.v_long = &v->dv_long; break;
58 case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break;
59 case LTTV_FLOAT: va.v_float = &v->dv_float; break;
60 case LTTV_DOUBLE: va.v_double = &v->dv_double; break;
61 case LTTV_TIME: va.v_time = &v->dv_time; break;
62 case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break;
63 case LTTV_STRING: va.v_string = &v->dv_string; break;
64 case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break;
65 case LTTV_NONE: break;
66 }
67 return va;
68 }
69
70
71 AttributeValue
72 init_value(LttvAttributeType t)
73 {
74 AttributeValue v;
75
76 switch(t) {
77 case LTTV_INT: v.dv_int = 0; break;
78 case LTTV_UINT: v.dv_uint = 0; break;
79 case LTTV_LONG: v.dv_long = 0; break;
80 case LTTV_ULONG: v.dv_ulong = 0; break;
81 case LTTV_FLOAT: v.dv_float = 0; break;
82 case LTTV_DOUBLE: v.dv_double = 0; break;
83 case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break;
84 case LTTV_POINTER: v.dv_pointer = NULL; break;
85 case LTTV_STRING: v.dv_string = NULL; break;
86 case LTTV_GOBJECT: v.dv_gobject = NULL; break;
87 case LTTV_NONE: break;
88 }
89 return v;
90 }
91
92
93 unsigned int
94 lttv_attribute_get_number(LttvAttribute *self)
95 {
96 return self->attributes->len;
97 }
98
99 gboolean
100 lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
101 {
102 *homogeneous = FALSE;
103 return TRUE;
104 }
105
106 LttvAttributeType
107 lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
108 LttvAttributeValue *v, gboolean *is_named)
109 {
110 Attribute *a;
111
112 a = &g_array_index(self->attributes, Attribute, i);
113 *name = a->name;
114 *v = address_of_value(a->type, &(a->value));
115 *is_named = a->is_named;
116 return a->type;
117 }
118
119
120 LttvAttributeType
121 lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
122 LttvAttributeValue *v)
123 {
124 Attribute *a;
125
126 unsigned i;
127
128 gpointer p;
129
130 p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
131 if(p == NULL) return LTTV_NONE;
132
133 i = GPOINTER_TO_UINT(p);
134 i--;
135 a = &g_array_index(self->attributes, Attribute, i);
136 *v = address_of_value(a->type, &(a->value));
137 return a->type;
138 }
139
140
141 LttvAttributeValue
142 lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
143 LttvAttributeType t)
144 {
145 unsigned int i;
146
147 Attribute a, *pa;
148
149 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
150 if(i != 0) g_error("duplicate entry in attribute table");
151
152 a.name = name;
153 a.is_named = 1;
154 a.type = t;
155 a.value = init_value(t);
156 g_array_append_val(self->attributes, a);
157 i = self->attributes->len - 1;
158 pa = &g_array_index(self->attributes, Attribute, i);
159 g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
160 GUINT_TO_POINTER(i + 1));
161 return address_of_value(t, &(pa->value));
162 }
163
164 LttvAttributeValue
165 lttv_attribute_add_unnamed(LttvAttribute *self, LttvAttributeName name,
166 LttvAttributeType t)
167 {
168 unsigned int i;
169
170 Attribute a, *pa;
171
172 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
173 if(i != 0) g_error("duplicate entry in attribute table");
174
175 a.name = name;
176 a.is_named = 0;
177 a.type = t;
178 a.value = init_value(t);
179 g_array_append_val(self->attributes, a);
180 i = self->attributes->len - 1;
181 pa = &g_array_index(self->attributes, Attribute, i);
182 g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
183 GUINT_TO_POINTER(i + 1));
184 return address_of_value(t, &(pa->value));
185 }
186
187
188 /* Remove an attribute */
189
190 void
191 lttv_attribute_remove(LttvAttribute *self, unsigned i)
192 {
193 Attribute *a;
194
195 a = &g_array_index(self->attributes, Attribute, i);
196
197 /* If the element is a gobject, unreference it. */
198 if(a->type == LTTV_GOBJECT && a->value.dv_gobject != NULL)
199 g_object_unref(a->value.dv_gobject);
200
201 /* Remove the array element and its entry in the name index */
202
203 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
204 g_array_remove_index_fast(self->attributes, i);
205
206 /* The element used to replace the removed element has its index entry
207 all wrong now. Reinsert it with its new position. */
208
209 if(likely(self->attributes->len != i)){
210 g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
211 g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
212 }
213 }
214
215 void
216 lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
217 {
218 unsigned int i;
219
220 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
221 if(unlikely(i == 0)) g_error("remove by name non existent attribute");
222
223 lttv_attribute_remove(self, i - 1);
224 }
225
226 /* Create an empty iattribute object and add it as an attribute under the
227 specified name, or return an existing iattribute attribute. If an
228 attribute of that name already exists but is not a GObject supporting the
229 iattribute interface, return NULL. */
230
231 /*CHECK*/LttvAttribute*
232 lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
233 {
234 unsigned int i;
235
236 Attribute a;
237
238 LttvAttribute *new;
239
240 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
241 if(likely(i != 0)) {
242 a = g_array_index(self->attributes, Attribute, i - 1);
243 if(likely(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject))) {
244 return LTTV_ATTRIBUTE(a.value.dv_gobject);
245 }
246 else return NULL;
247 }
248 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
249 *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
250 return (LttvAttribute *)new;
251 }
252
253 /*CHECK*/LttvAttribute*
254 lttv_attribute_find_subdir_unnamed(LttvAttribute *self, LttvAttributeName name)
255 {
256 unsigned int i;
257
258 Attribute a;
259
260 LttvAttribute *new;
261
262 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
263 if(likely(i != 0)) {
264 a = g_array_index(self->attributes, Attribute, i - 1);
265 if(likely(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject))) {
266 return LTTV_ATTRIBUTE(a.value.dv_gobject);
267 }
268 else return NULL;
269 }
270 new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
271 *(lttv_attribute_add_unnamed(self, name, LTTV_GOBJECT).v_gobject)
272 = G_OBJECT(new);
273 return (LttvAttribute *)new;
274 }
275
276 gboolean
277 lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
278 LttvAttributeType t, LttvAttributeValue *v)
279 {
280 unsigned int i;
281
282 Attribute *a;
283
284 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
285 if(likely(i != 0)) {
286 a = &g_array_index(self->attributes, Attribute, i - 1);
287 if(unlikely(a->type != t)) return FALSE;
288 *v = address_of_value(t, &(a->value));
289 return TRUE;
290 }
291
292 *v = lttv_attribute_add(self, name, t);
293 return TRUE;
294 }
295
296 gboolean
297 lttv_attribute_find_unnamed(LttvAttribute *self, LttvAttributeName name,
298 LttvAttributeType t, LttvAttributeValue *v)
299 {
300 unsigned i;
301
302 Attribute *a;
303
304 i = GPOINTER_TO_UINT(g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)));
305 if(likely(i != 0)) {
306 a = &g_array_index(self->attributes, Attribute, i - 1);
307 if(unlikely(a->type != t)) return FALSE;
308 *v = address_of_value(t, &(a->value));
309 return TRUE;
310 }
311
312 *v = lttv_attribute_add_unnamed(self, name, t);
313 return TRUE;
314 }
315
316
317 /*void lttv_attribute_recursive_free(LttvAttribute *self)
318 {
319 int i, nb;
320
321 Attribute *a;
322
323 nb = self->attributes->len;
324
325 for(i = 0 ; i < nb ; i++) {
326 a = &g_array_index(self->attributes, Attribute, i);
327 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
328 lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
329 }
330 }
331 g_object_unref(self);
332 }*/
333
334
335 void
336 lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
337 {
338 int i, nb;
339
340 Attribute *a;
341
342 LttvAttributeValue value;
343 gboolean retval;
344
345 nb = src->attributes->len;
346
347 for(i = 0 ; i < nb ; i++) {
348 a = &g_array_index(src->attributes, Attribute, i);
349 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
350 if(a->is_named)
351 lttv_attribute_recursive_add(
352 /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
353 (LttvAttribute *)(a->value.dv_gobject));
354 else
355 lttv_attribute_recursive_add(
356 /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir_unnamed(
357 dest, a->name), (LttvAttribute *)(a->value.dv_gobject));
358 }
359 else {
360 if(a->is_named) {
361 retval= lttv_attribute_find(dest, a->name, a->type, &value);
362 g_assert(retval);
363 }
364 else {
365 retval= lttv_attribute_find_unnamed(dest, a->name, a->type, &value);
366 g_assert(retval);
367 }
368 switch(a->type) {
369 case LTTV_INT:
370 *value.v_int += a->value.dv_int;
371 break;
372 case LTTV_UINT:
373 *value.v_uint += a->value.dv_uint;
374 break;
375 case LTTV_LONG:
376 *value.v_long += a->value.dv_long;
377 break;
378 case LTTV_ULONG:
379 *value.v_ulong += a->value.dv_ulong;
380 break;
381 case LTTV_FLOAT:
382 *value.v_float += a->value.dv_float;
383 break;
384 case LTTV_DOUBLE:
385 *value.v_double += a->value.dv_double;
386 break;
387 case LTTV_TIME:
388 *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
389 break;
390 case LTTV_POINTER:
391 break;
392 case LTTV_STRING:
393 break;
394 case LTTV_GOBJECT:
395 break;
396 case LTTV_NONE:
397 break;
398 }
399 }
400 }
401 }
402
403
404 static void
405 print_indent(FILE *fp, int pos)
406 {
407 int i;
408
409 for(i = 0 ; i < pos ; i++) putc(' ', fp);
410 }
411
412
413 void
414 lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent)
415 {
416 int i, nb;
417
418 Attribute *a;
419
420 nb = self->attributes->len;
421
422 fprintf(fp,"<ATTRS>\n");
423 for(i = 0 ; i < nb ; i++) {
424 a = &g_array_index(self->attributes, Attribute, i);
425 print_indent(fp, pos);
426 fprintf(fp, "<ATTR NAME=\"%s\" ", g_quark_to_string(a->name));
427 if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
428 fprintf(fp, "TYPE=ATTRS>");
429 lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp,
430 pos + indent, indent);
431 }
432 else {
433 switch(a->type) {
434 case LTTV_INT:
435 fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int);
436 break;
437 case LTTV_UINT:
438 fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint);
439 break;
440 case LTTV_LONG:
441 fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long);
442 break;
443 case LTTV_ULONG:
444 fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong);
445 break;
446 case LTTV_FLOAT:
447 fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float);
448 break;
449 case LTTV_DOUBLE:
450 fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double);
451 break;
452 case LTTV_TIME:
453 fprintf(fp, "TYPE=TIME SEC=%lu NSEC=%lu/>\n",
454 a->value.dv_time.tv_sec, a->value.dv_time.tv_nsec);
455 break;
456 case LTTV_POINTER:
457 fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer);
458 break;
459 case LTTV_STRING:
460 fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string);
461 break;
462 case LTTV_GOBJECT:
463 fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject);
464 break;
465 case LTTV_NONE:
466 fprintf(fp, "TYPE=NONE/>\n");
467 break;
468 }
469 }
470 }
471 print_indent(fp, pos);
472 fprintf(fp,"</ATTRS>\n");
473 }
474
475
476 void
477 lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
478 {
479 int res;
480
481 char buffer[256], type[10];
482
483 LttvAttributeName name;
484
485 LttvAttributeValue value;
486
487 LttvAttribute *subtree;
488
489 res = fscanf(fp, "<ATTRS>");
490 g_assert(res > 0);
491 while(1) {
492 res = fscanf(fp, "<ATTR NAME=\"%256[^\"]\" TYPE=%10[^ >]", buffer, type);
493 g_assert(res == 2);
494 name = g_quark_from_string(buffer);
495 if(strcmp(type, "ATTRS") == 0) {
496 res = fscanf(fp, ">");
497 g_assert(res > 0);
498 subtree = lttv_attribute_find_subdir(self, name);
499 lttv_attribute_read_xml(subtree, fp);
500 }
501 else if(strcmp(type, "INT") == 0) {
502 value = lttv_attribute_add(self, name, LTTV_INT);
503 res = fscanf(fp, " VALUE=%d/>", value.v_int);
504 g_assert(res == 1);
505 }
506 else if(strcmp(type, "UINT") == 0) {
507 value = lttv_attribute_add(self, name, LTTV_UINT);
508 res = fscanf(fp, " VALUE=%u/>", value.v_uint);
509 g_assert(res == 1);
510 }
511 else if(strcmp(type, "LONG") == 0) {
512 value = lttv_attribute_add(self, name, LTTV_LONG);
513 res = fscanf(fp, " VALUE=%ld/>", value.v_long);
514 g_assert(res == 1);
515 }
516 else if(strcmp(type, "ULONG") == 0) {
517 value = lttv_attribute_add(self, name, LTTV_ULONG);
518 res = fscanf(fp, " VALUE=%lu/>", value.v_ulong);
519 g_assert(res == 1);
520 }
521 else if(strcmp(type, "FLOAT") == 0) {
522 float d;
523 value = lttv_attribute_add(self, name, LTTV_FLOAT);
524 res = fscanf(fp, " VALUE=%f/>", &d);
525 *(value.v_float) = d;
526 g_assert(res == 1);
527 }
528 else if(strcmp(type, "DOUBLE") == 0) {
529 value = lttv_attribute_add(self, name, LTTV_DOUBLE);
530 res = fscanf(fp, " VALUE=%lf/>", value.v_double);
531 g_assert(res == 1);
532 }
533 else if(strcmp(type, "TIME") == 0) {
534 value = lttv_attribute_add(self, name, LTTV_TIME);
535 res = fscanf(fp, " SEC=%lu NSEC=%lu/>", &(value.v_time->tv_sec),
536 &(value.v_time->tv_nsec));
537 g_assert(res == 2);
538 }
539 else if(strcmp(type, "POINTER") == 0) {
540 value = lttv_attribute_add(self, name, LTTV_POINTER);
541 res = fscanf(fp, " VALUE=%p/>", value.v_pointer);
542 g_error("Cannot read a pointer");
543 }
544 else if(strcmp(type, "STRING") == 0) {
545 value = lttv_attribute_add(self, name, LTTV_STRING);
546 res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer);
547 *(value.v_string) = g_strdup(buffer);
548 g_assert(res == 1);
549 }
550 else if(strcmp(type, "GOBJECT") == 0) {
551 value = lttv_attribute_add(self, name, LTTV_GOBJECT);
552 res = fscanf(fp, " VALUE=%p/>", value.v_gobject);
553 g_error("Cannot read a pointer");
554 }
555 else if(strcmp(type, "NONE") == 0) {
556 value = lttv_attribute_add(self, name, LTTV_NONE);
557 res = fscanf(fp, "/>");
558 g_assert(res > 0);
559 }
560 else g_error("Unknown type to read");
561 }
562 res = fscanf(fp, "</ATTRS>");
563 g_assert(res > 0);
564 }
565
566 static LttvAttribute *
567 new_attribute (LttvAttribute *self)
568 {
569 return g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
570 }
571
572
573 static void
574 attribute_interface_init (gpointer g_iface, gpointer iface_data)
575 {
576 LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
577
578 klass->new_attribute = (LttvIAttribute* (*) (LttvIAttribute *self))
579 new_attribute;
580
581 klass->get_number = (unsigned int (*) (LttvIAttribute *self))
582 lttv_attribute_get_number;
583
584 klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
585 lttv_attribute_named;
586
587 klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
588 LttvAttributeName *name, LttvAttributeValue *v, gboolean *is_named))
589 lttv_attribute_get;
590
591 klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
592 LttvAttributeName name, LttvAttributeValue *v))
593 lttv_attribute_get_by_name;
594
595 klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
596 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
597
598 klass->add_unnamed = (LttvAttributeValue (*) (LttvIAttribute *self,
599 LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add_unnamed;
600
601 klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
602 lttv_attribute_remove;
603
604 klass->remove_by_name = (void (*) (LttvIAttribute *self,
605 LttvAttributeName name)) lttv_attribute_remove_by_name;
606
607 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
608 LttvAttributeName name)) lttv_attribute_find_subdir;
609
610 klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
611 LttvAttributeName name)) lttv_attribute_find_subdir_unnamed;
612 }
613
614 static void
615 attribute_instance_init (GTypeInstance *instance, gpointer g_class)
616 {
617 LttvAttribute *self = (LttvAttribute *)instance;
618 self->names = g_hash_table_new(g_direct_hash,
619 g_direct_equal);
620 self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
621 }
622
623
624 static void
625 attribute_finalize (LttvAttribute *self)
626 {
627 guint i;
628 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
629
630 for(i=0;i<self->attributes->len;i++) {
631 lttv_attribute_remove(self, i);
632 }
633
634 g_hash_table_destroy(self->names);
635 g_array_free(self->attributes, TRUE);
636 }
637
638
639 static void
640 attribute_class_init (LttvAttributeClass *klass)
641 {
642 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
643
644 gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
645 }
646
647 GType
648 lttv_attribute_get_type (void)
649 {
650 static GType type = 0;
651 if (type == 0) {
652 static const GTypeInfo info = {
653 sizeof (LttvAttributeClass),
654 NULL, /* base_init */
655 NULL, /* base_finalize */
656 (GClassInitFunc) attribute_class_init, /* class_init */
657 NULL, /* class_finalize */
658 NULL, /* class_data */
659 sizeof (LttvAttribute),
660 0, /* n_preallocs */
661 (GInstanceInitFunc) attribute_instance_init, /* instance_init */
662 NULL /* value handling */
663 };
664
665 static const GInterfaceInfo iattribute_info = {
666 (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
667 NULL, /* interface_finalize */
668 NULL /* interface_data */
669 };
670
671 type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
672 0);
673 g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
674 }
675 return type;
676 }
677
678
This page took 0.041873 seconds and 4 git commands to generate.