Add type class/type structure management
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 26 Feb 2011 20:01:16 +0000 (15:01 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 26 Feb 2011 20:01:16 +0000 (15:01 -0500)
Also add new "variant" type.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
15 files changed:
formats/ctf/ctf.c
formats/ctf/types/enum.c
formats/ctf/types/variant.c [new file with mode: 0644]
include/babeltrace/ctf/metadata.h [new file with mode: 0644]
include/babeltrace/format.h
include/babeltrace/types.h
types/array.c
types/enum.c
types/float.c
types/integer.c
types/sequence.c
types/string.c
types/struct.c
types/types.c
types/variant.c [new file with mode: 0644]

index c8a3712235ae749215e906f342921a926605f7a8..580133cc86c873fef4225e0bf3fbd65ff2019bb8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Format registration.
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -37,6 +37,8 @@ static struct format ctf_format = {
        .enum_write = ctf_enum_write,
        .struct_begin = ctf_struct_begin,
        .struct_end = ctf_struct_end,
+       .variant_begin = ctf_variant_begin,
+       .variant_end = ctf_variant_end,
        .array_begin = ctf_array_begin,
        .array_end = ctf_array_end,
        .sequence_begin = ctf_sequence_begin,
index e0bb545b72963b18fcb7f9c860c6309f00bfac25..6243345140d1b5b196278daf80f3a3d447857d87 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Enumeration mapping strings (quarks) from/to integers.
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -20,6 +20,9 @@
 #include <stdint.h>
 #include <glib.h>
 
+/*
+ * The caller should unref the GArray.
+ */
 GArray *ctf_enum_read(struct stream_pos *pos,
                      const struct type_class_enum *src)
 {
diff --git a/formats/ctf/types/variant.c b/formats/ctf/types/variant.c
new file mode 100644 (file)
index 0000000..78adca3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Common Trace Format
+ *
+ * Variant format access functions.
+ *
+ * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <babeltrace/ctf/types.h>
+
+void ctf_variant_begin(struct stream_pos *pos,
+                      const struct type_class_variant *variant_class)
+{
+}
+
+void ctf_variant_end(struct stream_pos *pos,
+                    const struct type_class_variant *variant_class)
+{
+}
diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h
new file mode 100644 (file)
index 0000000..622ed7b
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _BABELTRACE_CTF_METADATA_H
+#define _BABELTRACE_CTF_METADATA_H
+
+/*
+ * BabelTrace
+ *
+ * CTF Metadata Header
+ *
+ * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <babeltrace/types.h>
+#include <glib.h>
+
+struct ctf_trace;
+struct ctf_stream;
+struct ctf_event;
+
+struct ctf_trace {
+       struct declaration_scope *scope;
+};
+
+struct ctf_stream {
+       struct declaration_scope *scope;
+       GArray *events_by_id;   /* Array of struct ctf_event indexed by id */
+       GHashTable *event_quark_to_id;  /* GQuark to numeric id */
+};
+
+
+struct ctf_event {
+       struct declaration_scope *scope;
+       GQuark qname;
+};
+
+#endif /* _BABELTRACE_CTF_METADATA_H */
index b9c3e9fb0b029845ae280260d454a558cb070e1b..24276fa46915275f7b059edde605ad59cef65a70 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Trace Format Header
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -67,6 +67,10 @@ struct format {
                             const struct type_class_struct *struct_class);
        void (*struct_end)(struct stream_pos *pos,
                           const struct type_class_struct *struct_class);
+       void (*variant_begin)(struct stream_pos *pos,
+                             const struct type_class_variant *variant_class);
+       void (*variant_end)(struct stream_pos *pos,
+                           const struct type_class_variant *variant_class);
        void (*array_begin)(struct stream_pos *pos,
                             const struct type_class_array *array_class);
        void (*array_end)(struct stream_pos *pos,
index a315c4c387cbbf517963fdb0bb48cadfe1b0bf2f..242b905761b99b5695aa3d18fee40b57599cab2f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Type Header
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -85,19 +85,34 @@ char *get_pos_addr(struct stream_pos *pos)
 }
 
 struct format;
+struct type;
 
 struct type_class {
        GQuark name;            /* type name */
        size_t alignment;       /* type alignment, in bits */
-       int ref;                /* number of references to the type */
+       int ref;                /* number of references to the type class */
        /*
-        * Type copy function. Knows how to find the child type_class from the
-        * parent type_class.
+        * class_free called with type class ref is decremented to 0.
+        */
+       void (*class_free)(struct type_class *type_class);
+       struct type *(*type_new)(struct type_class *_class,
+                                struct declaration_scope *parent_scope);
+       /*
+        * type_free called with type ref is decremented to 0.
+        */
+       void (*type_free)(struct type *type);
+       /*
+        * Type copy function. Knows how to find the child type from the parent
+        * type.
         */
        void (*copy)(struct stream_pos *dest, const struct format *fdest, 
                     struct stream_pos *src, const struct format *fsrc,
-                    const struct type_class *type_class);
-       void (*free)(struct type_class *type_class);
+                    struct type *type);
+};
+
+struct type {
+       struct type_class *_class;
+       int ref;                /* number of references to the type instance */
 };
 
 /*
@@ -112,6 +127,16 @@ struct type_class_integer {
        int signedness;
 };
 
+struct type_integer {
+       struct type p;
+       struct type_class_integer *_class;
+       /* Last values read */
+       union {
+               uint64_t _unsigned;
+               int64_t _signed;
+       } value;
+};
+
 struct type_class_float {
        struct type_class p;
        struct type_class_integer *sign;
@@ -121,6 +146,13 @@ struct type_class_float {
        /* TODO: we might want to express more info about NaN, +inf and -inf */
 };
 
+struct type_float {
+       struct type p;
+       struct type_class_float *_class;
+       /* Last values read */
+       long double value;
+};
+
 /*
  * enum_val_equal assumes that signed and unsigned memory layout overlap.
  */
@@ -164,19 +196,58 @@ struct type_class_enum {
        struct enum_table table;
 };
 
+struct type_enum {
+       struct type p;
+       struct type_class_enum *_class;
+       /* Last GQuark values read. Keeping a reference on the GQuark array. */
+       GArray *value;
+};
+
 struct type_class_string {
        struct type_class p;
 };
 
-struct field {
+struct type_string {
+       struct type p;
+       struct type_class_string *_class;
+       char *value;    /* freed at type_string teardown */
+};
+
+struct type_class_field {
        GQuark name;
        struct type_class *type_class;
 };
 
+struct field {
+       struct type *type;
+};
+
 struct type_class_struct {
        struct type_class p;
        GHashTable *fields_by_name;     /* Tuples (field name, field index) */
-       GArray *fields;                 /* Array of fields */
+       GArray *fields;                 /* Array of type_class_field */
+};
+
+struct type_struct {
+       struct type p;
+       struct type_class_struct *_class;
+       struct declaration_scope *scope;
+       GArray *fields;                 /* Array of struct field */
+};
+
+struct type_class_variant {
+       struct type_class p;
+       GHashTable *fields_by_tag;      /* Tuples (field tag, field index) */
+       GArray *fields;                 /* Array of type_class_field */
+};
+
+struct type_variant {
+       struct type p;
+       struct type_class_variant *_class;
+       struct declaration_scope *scope;
+       struct type *tag;
+       GArray *fields;                 /* Array of struct field */
+       struct field *current_field;    /* Last field read */
 };
 
 struct type_class_array {
@@ -185,35 +256,64 @@ struct type_class_array {
        struct type_class *elem;
 };
 
+struct type_array {
+       struct type p;
+       struct type_class_array *_class;
+       struct declaration_scope *scope;
+       struct field current_element;           /* struct field */
+};
+
 struct type_class_sequence {
        struct type_class p;
        struct type_class_integer *len_class;
        struct type_class *elem;
 };
 
-struct type_class *lookup_type(GQuark qname);
-int register_type(struct type_class *type_class);
+struct type_sequence {
+       struct type p;
+       struct type_class_sequence *_class;
+       struct declaration_scope *scope;
+       struct type_integer *len;
+       struct field current_element;           /* struct field */
+};
+
+/* Type declaration scope */
+struct declaration_scope {
+       /* Hash table mapping type name GQuark to struct type_class */
+       GHashTable *type_classes;
+       struct declaration_scope *parent_scope;
+};
+
+struct type_class *lookup_type_class(GQuark qname,
+                                    struct declaration_scope *scope);
+int register_type_class(struct type_class *type_class,
+                       struct declaration_scope *scope);
+
+void type_class_ref(struct type_class *type_class);
+void type_class_unref(struct type_class *type_class);
+
+struct declaration_scope *
+new_declaration_scope(struct declaration_scope *parent_scope);
+void free_declaration_scope(struct declaration_scope *scope);
 
-void type_ref(struct type_class *type_class);
-void type_unref(struct type_class *type_class);
+void type_ref(struct type *type);
+void type_unref(struct type *type);
 
 /* Nameless types can be created by passing a NULL name */
 
-struct type_class_integer *integer_type_new(const char *name,
+struct type_class_integer *integer_type_class_new(const char *name,
                                            size_t len, int byte_order,
                                            int signedness,
                                            size_t alignment);
-void integer_type_free(struct type_class_integer *int_class);
 
 /*
  * mantissa_len is the length of the number of bytes represented by the mantissa
  * (e.g. result of DBL_MANT_DIG). It includes the leading 1.
  */
-struct type_class_float *float_type_new(const char *name,
+struct type_class_float *float_type_class_new(const char *name,
                                        size_t mantissa_len,
                                        size_t exp_len, int byte_order,
                                        size_t alignment);
-void float_type_free(struct type_class_float *float_class);
 
 /*
  * A GQuark can be translated to/from strings with g_quark_from_string() and
@@ -245,47 +345,72 @@ void enum_signed_insert(struct type_class_enum *enum_class,
                         int64_t start, int64_t end, GQuark q);
 void enum_unsigned_insert(struct type_class_enum *enum_class,
                          uint64_t start, uint64_t end, GQuark q);
+size_t enum_get_nr_enumerators(struct type_class_enum *enum_class);
 
-struct type_class_enum *enum_type_new(const char *name,
+struct type_class_enum *enum_type_class_new(const char *name,
                                      size_t len, int byte_order,
                                      int signedness,
                                      size_t alignment);
-void enum_type_free(struct type_class_enum *enum_class);
 
-struct type_class_struct *struct_type_new(const char *name);
-void struct_type_free(struct type_class_struct *struct_class);
-void struct_type_add_field(struct type_class_struct *struct_class,
-                          const char *field_name,
-                          struct type_class *type_class);
+struct type_class_struct *struct_type_class_new(const char *name);
+void struct_type_class_add_field(struct type_class_struct *struct_class,
+                                const char *field_name,
+                                struct type_class *type_class);
 /*
  * Returns the index of a field within a structure.
  */
 unsigned long
-struct_type_lookup_field_index(struct type_class_struct *struct_class,
-                              GQuark field_name);
+struct_type_class_lookup_field_index(struct type_class_struct *struct_class,
+                                    GQuark field_name);
 /*
  * field returned only valid as long as the field structure is not appended to.
  */
+struct type_class_field *
+struct_type_class_get_field_from_index(struct type_class_struct *struct_class,
+                                      unsigned long index);
 struct field *
-struct_type_get_field_from_index(struct type_class_struct *struct_class,
+struct_type_get_field_from_index(struct type_struct *_struct,
                                 unsigned long index);
 
+/*
+ * The tag enumeration is validated to ensure that it contains only mappings
+ * from numeric values to a single tag. Overlapping tag value ranges are
+ * therefore forbidden.
+ */
+struct type_class_variant *variant_type_class_new(const char *name);
+void variant_type_class_add_field(struct type_class_variant *variant_class,
+                                 const char *tag_name,
+                                 struct type_class *type_class);
+struct type_class_field *
+variant_type_class_get_field_from_tag(struct type_class_variant *variant_class,
+                                     GQuark tag);
+/*
+ * Returns 0 on success, -EPERM on error.
+ */
+int variant_type_set_tag(struct type_variant *variant,
+                        struct type *enum_tag_instance);
+/*
+ * Returns the field selected by the current tag value.
+ * field returned only valid as long as the variant structure is not appended
+ * to.
+ */
+struct field *
+variant_type_get_current_field(struct type_variant *variant);
+
 /*
  * elem_class passed as parameter now belongs to the array. No need to free it
- * explicitely.
+ * explicitly. "len" is the number of elements in the array.
  */
-struct type_class_array *array_type_new(const char *name,
+struct type_class_array *array_type_class_new(const char *name,
                                        size_t len,
                                        struct type_class *elem_class);
-void array_type_free(struct type_class_array *array_class);
 
 /*
  * int_class and elem_class passed as parameter now belongs to the sequence. No
- * need to free them explicitely.
+ * need to free them explicitly.
  */
-struct type_class_sequence *sequence_type_new(const char *name,
+struct type_class_sequence *sequence_type_class_new(const char *name,
                                        struct type_class_integer *len_class, 
                                        struct type_class *elem_class);
-void sequence_type_free(struct type_class_sequence *sequence_class);
 
 #endif /* _BABELTRACE_TYPES_H */
index 01483b520017e4fbfb84fd5800fbb029babdae46..6ac4a1a1cbfab26b06ef5648380b48ceb1264d95 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Array Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <babeltrace/compiler.h>
 #include <babeltrace/format.h>
 
+static
+struct type *_array_type_new(struct type_class *type_class,
+                            struct declaration_scope *parent_scope);
+static
+void _array_type_free(struct type *type);
+
 void array_copy(struct stream_pos *dest, const struct format *fdest, 
                struct stream_pos *src, const struct format *fsrc,
-               const struct type_class *type_class)
+               struct type *type)
 {
-       struct type_class_array *array_class =
-               container_of(type_class, struct type_class_array, p);
-       unsigned int i;
+       struct type_sequence *array = container_of(type, struct type_array, p);
+       struct type_class_array *array_class = array->_class;
+       uint64_t i;
 
        fsrc->array_begin(src, array_class);
        fdest->array_begin(dest, array_class);
 
        for (i = 0; i < array_class->len; i++) {
-               struct type_class *elem_class = array_class->elem;
-               elem_class->copy(dest, fdest, src, fsrc, elem_class);
+               struct type_class *elem_class = array->current_element.type;
+               elem_type->p._class->copy(dest, fdest, src, fsrc, elem_type);
        }
        fsrc->array_end(src, array_class);
        fdest->array_end(dest, array_class);
 }
 
-void array_type_free(struct type_class_array *array_class)
-{
-       type_unref(array_class->elem);
-       g_free(array_class);
-}
-
-static void _array_type_free(struct type_class *type_class)
+static
+void _array_type_class_free(struct type_class *type_class)
 {
        struct type_class_array *array_class =
                container_of(type_class, struct type_class_array, p);
-       array_type_free(array_class);
+
+       type_class_unref(array_class->elem);
+       g_free(array_class);
 }
 
-struct type_class_array *array_type_new(const char *name, size_t len,
-                                       struct type_class *elem)
+struct type_class_array *
+array_type_class_new(const char *name, size_t len, struct type_class *elem)
 {
        struct type_class_array *array_class;
        struct type_class *type_class;
@@ -60,7 +63,6 @@ struct type_class_array *array_type_new(const char *name, size_t len,
 
        array_class = g_new(struct type_class_array, 1);
        type_class = &array_class->p;
-
        array_class->len = len;
        type_ref(elem);
        array_class->elem = elem;
@@ -68,7 +70,9 @@ struct type_class_array *array_type_new(const char *name, size_t len,
        /* No need to align the array, the first element will align itself */
        type_class->alignment = 1;
        type_class->copy = array_copy;
-       type_class->free = _array_type_free;
+       type_class->class_free = _array_type_class_free;
+       type_class->type_new = _array_type_new;
+       type_class->type_free = _array_type_free;
        type_class->ref = 1;
 
        if (type_class->name) {
@@ -79,7 +83,39 @@ struct type_class_array *array_type_new(const char *name, size_t len,
        return array_class;
 
 error_register:
-       type_unref(array_class->elem);
+       type_class_unref(array_class->elem);
        g_free(array_class);
        return NULL;
 }
+
+static
+struct type_array *_array_type_new(struct type_class *type_class,
+                                  struct declaration_scope *parent_scope)
+{
+       struct type_class_array *array_class =
+               container_of(type_class, struct type_class_array, p);
+       struct type_array *array;
+
+       array = g_new(struct type_array, 1);
+       type_class_ref(&array_class->p);
+       array->p._class = array_class;
+       array->p.ref = 1;
+       array->scope = new_declaration_scope(parent_scope);
+       array->current_element.type =
+               array_class->elem.p->type_new(&array_class->elem.p,
+                                                parent_scope);
+       return &array->p;
+}
+
+static
+void _array_type_free(struct type *type)
+{
+       struct type_array *array =
+               container_of(type, struct type_array, p);
+       struct type *elem_type = array->current_element.type;
+
+       elem_type->p._class->type_free(elem_type);
+       free_declaration_scope(array->scope);
+       type_class_unref(array->p._class);
+       g_free(array);
+}
index 6ad4d45038eabf37da04b05944b290d3bff983fe..109fd2815a2d1a3780a8a01378fdd10e6ba6f93b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Enumeration Type
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <stdint.h>
 #include <glib.h>
 
+static
+struct type_enum *_enum_type_new(struct type_class *type_class,
+                                struct declaration_scope *parent_scope);
+static
+void _enum_type_free(struct type *type);
+
 static
 void enum_range_set_free(void *ptr)
 {
@@ -336,17 +342,26 @@ void enum_unsigned_insert(struct type_class_enum *enum_class,
        range->end._unsigned = end;
 }
 
+size_t enum_get_nr_enumerators(struct type_class_enum *enum_class)
+{
+       return g_hash_table_size(enum_class->table.quark_to_range_set);
+}
+
 void enum_copy(struct stream_pos *dest, const struct format *fdest, 
               struct stream_pos *src, const struct format *fsrc,
-              const struct type_class *type_class)
+              struct type *type)
 {
-       struct type_class_enum *enum_class =
-               container_of(type_class, struct type_class_enum, p.p);
+       struct type_enum *_enum = container_of(type, struct type_enum, p);
+       struct type_class_enum *enum_class = _enum->_class;
        GArray *array;
        GQuark v;
 
        array = fsrc->enum_read(src, enum_class);
        assert(array);
+       /* unref previous array */
+       if (_enum->value)
+               g_array_unref(_enum->value, TRUE);
+       _enum->value = array;
        /*
         * Arbitrarily choose the first one.
         * TODO: use direct underlying type read/write intead. Not doing it for
@@ -356,8 +371,11 @@ void enum_copy(struct stream_pos *dest, const struct format *fdest,
        return fdest->enum_write(dest, enum_class, v);
 }
 
-void enum_type_free(struct type_class_enum *enum_class)
+static
+void _enum_type_class_free(struct type_class *type_class)
 {
+       struct type_class_enum *enum_class =
+               container_of(type_class, struct enum_type_class, p);
        struct enum_range_to_quark *iter, *tmp;
 
        g_hash_table_destroy(enum_class->table.value_to_quark_set);
@@ -369,18 +387,9 @@ void enum_type_free(struct type_class_enum *enum_class)
        g_free(enum_class);
 }
 
-static
-void _enum_type_free(struct type_class *type_class)
-{
-       struct type_class_enum *enum_class =
-               container_of(type_class, struct type_class_enum, p.p);
-       enum_type_free(enum_class);
-}
-
-struct type_class_enum *enum_type_new(const char *name,
-                                     size_t len, int byte_order,
-                                     int signedness,
-                                     size_t alignment)
+struct type_class_enum *
+_enum_type_class_new(const char *name, size_t len, int byte_order,
+                    int signedness, size_t alignment)
 {
        struct type_class_enum *enum_class;
        struct type_class_integer *int_class;
@@ -399,25 +408,58 @@ struct type_class_enum *enum_type_new(const char *name,
        int_class->p.name = g_quark_from_string(name);
        int_class->p.alignment = alignment;
        int_class->p.copy = enum_copy;
-       int_class->p.free = _enum_type_free;
+       int_class->p.class_free = _enum_type_class_free;
+       int_class->p.type_new = _enum_type_new;
+       int_class->p.type_free = _enum_type_free;
        int_class->p.ref = 1;
        int_class->len = len;
        int_class->byte_order = byte_order;
        int_class->signedness = signedness;
        if (int_class->p.name) {
                ret = register_type(&int_class->p);
-               if (ret) {
-                       struct enum_range_to_quark *iter, *tmp;
-
-                       g_hash_table_destroy(enum_class->table.value_to_quark_set);
-                       cds_list_for_each_entry_safe(iter, tmp, &enum_class->table.range_to_quark, node) {
-                               cds_list_del(&iter->node);
-                               g_free(iter);
-                       }
-                       g_hash_table_destroy(enum_class->table.quark_to_range_set);
-                       g_free(enum_class);
-                       return NULL;
-               }
+               if (ret)
+                       goto register_error;
        }
        return enum_class;
+
+register_error:
+       {
+               struct enum_range_to_quark *iter, *tmp;
+
+               cds_list_for_each_entry_safe(iter, tmp, &enum_class->table.range_to_quark, node) {
+                       cds_list_del(&iter->node);
+                       g_free(iter);
+               }
+       }
+       g_hash_table_destroy(enum_class->table.value_to_quark_set);
+       g_hash_table_destroy(enum_class->table.quark_to_range_set);
+       g_free(enum_class);
+       return NULL;
+}
+
+static
+struct type_enum *_enum_type_new(struct type_class *type_class,
+                                struct declaration_scope *parent_scope)
+{
+       struct type_class_enum *enum_class =
+               container_of(type_class, struct type_class_enum, p);
+       struct type_enum *_enum;
+
+       _enum = g_new(struct type_enum, 1);
+       type_class_ref(&enum_class->p);
+       _enum->p._class = enum_class;
+       _enum->p.ref = 1;
+       _enum->value = NULL;
+       return &_enum->p;
+}
+
+static
+void _enum_type_free(struct type *type)
+{
+       struct type_enum *_enum = container_of(type, struct type_enum, p);
+
+       type_class_unref(_enum->p._class);
+       if (_enum->value)
+               g_array_unref(_enum->value, TRUE);
+       g_free(_enum);
 }
index 2ce6b5929d50d5f5609ef1ee8c96787208acd9df..c78cf584feb4f07f9100ed5f8902a046f1027e01 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Float Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <babeltrace/compiler.h>
 #include <babeltrace/format.h>
 
+static
+struct type_float *_float_type_new(struct type_class *type_class,
+                                  struct declaration_scope *parent_scope);
+static
+void _float_type_free(struct type *type);
+
 void float_copy(struct stream_pos *destp,
                const struct format *fdest,
                struct stream_pos *srcp,
                const struct format *fsrc,
-               const struct type_class *type_class)
+               struct type *type)
 {
-       struct type_class_float *float_class =
-               container_of(type_class, struct type_class_float, p);
+       struct type_float *_float = container_of(type, struct type_float, p);
+       struct type_class_float *float_class = _float->_class;
 
        if (fsrc->float_copy == fdest->float_copy) {
                fsrc->float_copy(destp, srcp, float_class);
@@ -38,25 +44,21 @@ void float_copy(struct stream_pos *destp,
        }
 }
 
-void float_type_free(struct type_class_float *float_class)
-{
-       integer_type_free(float_class->exp);
-       integer_type_free(float_class->mantissa);
-       integer_type_free(float_class->sign);
-       g_free(float_class);
-}
-
-static void _float_type_free(struct type_class *type_class)
+static
+void _float_type_class_free(struct type_class *type_class)
 {
        struct type_class_float *float_class =
                container_of(type_class, struct type_class_float, p);
-       float_type_free(float_class);
+
+       type_class_unref(&float_class->exp->p);
+       type_class_unref(&float_class->mantissa->p);
+       type_class_unref(&float_class->sign->p);
+       g_free(float_class);
 }
 
-struct type_class_float *float_type_new(const char *name,
-                                       size_t mantissa_len,
-                                       size_t exp_len, int byte_order,
-                                       size_t alignment)
+struct type_class_float *
+float_type_class_new(const char *name, size_t mantissa_len,
+                    size_t exp_len, int byte_order, size_t alignment)
 {
        struct type_class_float *float_class;
        struct type_class *type_class;
@@ -64,11 +66,12 @@ struct type_class_float *float_type_new(const char *name,
 
        float_class = g_new(struct type_class_float, 1);
        type_class = &float_class->p;
-
        type_class->name = g_quark_from_string(name);
        type_class->alignment = alignment;
        type_class->copy = float_copy;
-       type_class->free = _float_type_free;
+       type_class->class_free = _float_type_class_free;
+       type_class->type_new = _float_type_new;
+       type_class->type_free = _float_type_free;
        type_class->ref = 1;
        float_class->byte_order = byte_order;
 
@@ -93,12 +96,37 @@ struct type_class_float *float_type_new(const char *name,
        return float_class;
 
 error_register:
-       integer_type_free(float_class->exp);
+       type_class_unref(&float_class->exp->p);
 error_exp:
-       integer_type_free(float_class->mantissa);
+       type_class_unref(&float_class->mantissa->p);
 error_mantissa:
-       integer_type_free(float_class->sign);
+       type_class_unref(&float_class->sign->p);
 error_sign:
        g_free(float_class);
        return NULL;
 }
+
+static
+struct type_float *_float_type_new(struct type_class *type_class,
+                                  struct declaration_scope *parent_scope)
+{
+       struct type_class_float *float_class =
+               container_of(type_class, struct type_class_float, p);
+       struct type_float *_float;
+
+       _float = g_new(struct type_float, 1);
+       type_class_ref(&_float_class->p);
+       _float->p._class = _float_class;
+       _float->p.ref = 1;
+       _float->value = 0.0;
+       return &_float->p;
+}
+
+static
+void _float_type_free(struct type *type)
+{
+       struct type_float *_float = container_of(type, struct type_float, p);
+
+       type_class_unref(_float->p._class);
+       g_free(_float);
+}
index 1e926f7b4041e4c4f19c0e745a010d0e62eb6e41..ea292900ce80886141bf21a171ec3b76d2573db8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Integer Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <babeltrace/format.h>
 #include <stdint.h>
 
+static
+struct type *_integer_type_new(struct type_class *type_class,
+                              struct declaration_scope *parent_scope);
+static
+void _integer_type_free(struct type *type);
+
 void integer_copy(struct stream_pos *dest, const struct format *fdest, 
                  struct stream_pos *src, const struct format *fsrc,
-                 const struct type_class *type_class)
+                 struct type *type)
 {
-       struct type_class_integer *int_class =
-               container_of(type_class, struct type_class_integer, p);
+       struct type_integer *integer = container_of(type, struct type_integer,
+                                                   p);
+       struct type_class_integer *int_class = integer->_class;
 
        if (!int_class->signedness) {
                uint64_t v;
@@ -41,22 +48,17 @@ void integer_copy(struct stream_pos *dest, const struct format *fdest,
        }
 }
 
-void integer_type_free(struct type_class_integer *int_class)
+static
+void _integer_type_class_free(struct type_class *type_class)
 {
-       g_free(int_class);
-}
-
-static void _integer_type_free(struct type_class *type_class)
-{
-       struct type_class_integer *int_class =
+       struct type_class_integer *integer_class =
                container_of(type_class, struct type_class_integer, p);
-       integer_type_free(int_class);
+       g_free(integer_class);
 }
 
-struct type_class_integer *integer_type_new(const char *name,
-                                           size_t len, int byte_order,
-                                           int signedness,
-                                           size_t alignment)
+struct type_class_integer *
+integer_type_class_new(const char *name, size_t len, int byte_order,
+                      int signedness, size_t alignment)
 {
        struct type_class_integer *int_class;
        int ret;
@@ -65,7 +67,9 @@ struct type_class_integer *integer_type_new(const char *name,
        int_class->p.name = g_quark_from_string(name);
        int_class->p.alignment = alignment;
        int_class->p.copy = integer_copy;
-       int_class->p.free = _integer_type_free;
+       int_class->p.class_free = _integer_type_class_free;
+       int_class->p.type_free = _integer_type_free;
+       int_class->p.type_new = _integer_type_new;
        int_class->p.ref = 1;
        int_class->len = len;
        int_class->byte_order = byte_order;
@@ -79,3 +83,29 @@ struct type_class_integer *integer_type_new(const char *name,
        }
        return int_class;
 }
+
+static
+struct type_integer *_integer_type_new(struct type_class *type_class,
+                                      struct declaration_scope *parent_scope)
+{
+       struct type_class_integer *integer_class =
+               container_of(type_class, struct type_class_integer, p);
+       struct type_integer *integer;
+
+       integer = g_new(struct type_integer, 1);
+       type_class_ref(&integer_class->p);
+       integer->p._class = integer_class;
+       integer->p.ref = 1;
+       integer->value._unsigned = 0;
+       return &integer->p;
+}
+
+static
+void _integer_type_free(struct type *type)
+{
+       struct type_integer *integer =
+               container_of(type, struct type_integer, p);
+
+       type_class_unref(integer->p._class);
+       g_free(integer);
+}
index 4967182821d74a031fb7c4e5de6c51d18352cd4d..8f3fed9aff924105dee3220b67475f6a832dcc08 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Sequence Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #define max(a, b)      ((a) < (b) ? (b) : (a))
 #endif
 
+static
+struct type *_sequence_type_new(struct type_class *type_class,
+                               struct declaration_scope *parent_scope);
+static
+void _sequence_type_free(struct type *type);
+
 void sequence_copy(struct stream_pos *dest, const struct format *fdest, 
                   struct stream_pos *src, const struct format *fsrc,
-                  const struct type_class *type_class)
+                  struct type *type)
 {
-       struct type_class_sequence *sequence_class =
-               container_of(type_class, struct type_class_sequence, p);
-       unsigned int i;
-       size_t len;
+       struct type_sequence *sequence =
+               container_of(type, struct type_sequence, p);
+       struct type_class_sequence *sequence_class = sequence->_class;
+       uint64_t i;
 
-       fsrc->sequence_begin(src, sequence_class);
-       fdest->sequence_begin(dest, sequence_class);
+       fsrc->sequence_begin(src, sequence);
+       fdest->sequence_begin(dest, sequence);
 
-       len = fsrc->uint_read(src, sequence_class->len_class);
-       fdest->uint_write(dest, sequence_class->len_class, len);
+       sequence->len->p._class->copy(dest, fdest, src, fsrc,
+                                     &sequence->len->p);
 
-       for (i = 0; i < len; i++) {
-               struct type_class *elem_class = sequence_class->elem;
-               elem_class->copy(dest, fdest, src, fsrc, elem_class);
+       for (i = 0; i < sequence->len->value._unsigned; i++) {
+               struct type *elem_type = sequence->current_element.type;
+               elem_type->p._class->copy(dest, fdest, src, fsrc, elem_type);
        }
-       fsrc->sequence_end(src, sequence_class);
-       fdest->sequence_end(dest, sequence_class);
+       fsrc->sequence_end(src, sequence);
+       fdest->sequence_end(dest, sequence);
 }
 
-void sequence_type_free(struct type_class_sequence *sequence_class)
-{
-       sequence_class->elem->free(sequence_class->elem);
-       type_unref(&sequence_class->len_class->p);
-       type_unref(sequence_class->elem);
-       g_free(sequence_class);
-}
-
-static void _sequence_type_free(struct type_class *type_class)
+static
+void _sequence_type_class_free(struct type_class *type_class)
 {
        struct type_class_sequence *sequence_class =
                container_of(type_class, struct type_class_sequence, p);
-       sequence_type_free(sequence_class);
+
+       type_class_unref(&sequence_class->len_class->p);
+       type_class_unref(sequence_class->elem);
+       g_free(sequence_class);
 }
 
 struct type_class_sequence *
-sequence_type_new(const char *name, struct type_class_integer *len_class,
-                 struct type_class *elem)
+sequence_type_class_new(const char *name, struct type_class_integer *len_class,
+                       struct type_class *elem)
 {
        struct type_class_sequence *sequence_class;
        struct type_class *type_class;
@@ -71,9 +73,7 @@ sequence_type_new(const char *name, struct type_class_integer *len_class,
 
        sequence_class = g_new(struct type_class_sequence, 1);
        type_class = &sequence_class->p;
-
        assert(!len_class->signedness);
-
        type_ref(&len_class->p);
        sequence_class->len_class = len_class;
        type_ref(elem);
@@ -82,7 +82,9 @@ sequence_type_new(const char *name, struct type_class_integer *len_class,
        type_class->alignment = max(len_class->p.alignment,
                                    elem->alignment);
        type_class->copy = sequence_copy;
-       type_class->free = _sequence_type_free;
+       type_class->class_free = _sequence_type_class_free;
+       type_class->type_new = _sequence_type_new;
+       type_class->type_free = _sequence_type_free;
        type_class->ref = 1;
 
        if (type_class->name) {
@@ -93,8 +95,45 @@ sequence_type_new(const char *name, struct type_class_integer *len_class,
        return sequence_class;
 
 error_register:
-       type_unref(&len_class->p);
-       type_unref(elem);
+       type_class_unref(&len_class->p);
+       type_class_unref(elem);
        g_free(sequence_class);
        return NULL;
 }
+
+static
+struct type *_sequence_type_new(struct type_class *type_class,
+                               struct declaration_scope *parent_scope)
+{
+       struct type_class_sequence *sequence_class =
+               container_of(type_class, struct type_class_sequence, p);
+       struct type_sequence *sequence;
+
+       sequence = g_new(struct type_sequence, 1);
+       type_class_ref(&sequence_class->p);
+       sequence->p._class = sequence_class;
+       sequence->p.ref = 1;
+       sequence->scope = new_declaration_scope(parent_scope);
+       sequence->len.type =
+               sequence_class->len_class.p->type_new(&sequence_class->len_class.p,
+                                                     parent_scope);
+       sequence->current_element.type =
+               sequence_class->elem.p->type_new(&sequence_class->elem.p,
+                                                parent_scope);
+       return &sequence->p;
+}
+
+static
+void _sequence_type_free(struct type *type)
+{
+       struct type_sequence *sequence =
+               container_of(type, struct type_sequence, p);
+       struct type *len_type = sequence->len.type;
+       struct type *elem_type = sequence->current_element.type;
+
+       len_type->p._class->type_free(len_type);
+       elem_type->p._class->type_free(elem_type);
+       free_declaration_scope(sequence->scope);
+       type_class_unref(sequence->p._class);
+       g_free(sequence);
+}
index ab0ec72c30da53209355a229bf35aaefbd60867e..e76ac77ae7620def6537f415642ef8375bd9210d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - String Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <babeltrace/align.h>
 #include <babeltrace/format.h>
 
+static
+struct type_string *_string_type_new(struct type_class *type_class,
+                                    struct declaration_scope *parent_scope);
+static
+void _string_type_free(struct type *type);
+
 void string_copy(struct stream_pos *dest, const struct format *fdest, 
                 struct stream_pos *src, const struct format *fsrc,
-                const struct type_class *type_class)
+                struct type *type)
 {
-       struct type_class_string *string_class =
-               container_of(type_class, struct type_class_string, p);
+       struct type_string *string = container_of(type, struct type_string, p);
+       struct type_class_string *string_class = string->_class;
 
        if (fsrc->string_copy == fdest->string_copy) {
                fsrc->string_copy(dest, src, string_class);
@@ -38,19 +44,16 @@ void string_copy(struct stream_pos *dest, const struct format *fdest,
        }
 }
 
-void string_type_free(struct type_class_string *string_class)
-{
-       g_free(string_class);
-}
-
-static void _string_type_free(struct type_class *type_class)
+static
+void _string_type_class_free(struct type_class_string *string_class)
 {
        struct type_class_string *string_class =
                container_of(type_class, struct type_class_string, p);
-       string_type_free(string_class);
+       g_free(string_class);
 }
 
-struct type_class_string *string_type_new(const char *name)
+struct type_class_string *
+string_type_class_new(const char *name)
 {
        struct type_class_string *string_class;
        int ret;
@@ -59,7 +62,9 @@ struct type_class_string *string_type_new(const char *name)
        string_class->p.name = g_quark_from_string(name);
        string_class->p.alignment = CHAR_BIT;
        string_class->p.copy = string_copy;
-       string_class->p.free = _string_type_free;
+       string_class->p.class_free = _string_type_class_free;
+       string_class->p.type_new = _string_type_new;
+       string_class->p.type_free = _string_type_free;
        string_class->p.ref = 1;
        if (string_class->p.name) {
                ret = register_type(&string_class->p);
@@ -70,3 +75,30 @@ struct type_class_string *string_type_new(const char *name)
        }
        return string_class;
 }
+
+static
+struct type_string *_string_type_new(struct type_class *type_class,
+                                    struct declaration_scope *parent_scope)
+{
+       struct type_class_string *string_class =
+               container_of(type_class, struct type_class_string, p);
+       struct type_string *string;
+
+       string = g_new(struct type_string, 1);
+       type_class_ref(&string_class->p);
+       string->p._class = string_class;
+       string->p.ref = 1;
+       string->value = NULL;
+       return &string->p;
+}
+
+static
+void _string_type_free(struct type *type)
+{
+       struct type_string *string =
+               container_of(type, struct type_string, p);
+
+       type_class_unref(string->p._class);
+       g_free(string->value);
+       g_free(string);
+}
index d3e9f3c484cd11e88aeed88daeb4003a03623c5b..1e1b458a91f531445fad1409c4c6a089d75972ab 100644 (file)
@@ -3,7 +3,7 @@
  *
  * BabelTrace - Structure Type Converter
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #define max(a, b)      ((a) < (b) ? (b) : (a))
 #endif
 
+static
+struct type *_struct_type_new(struct type_class *type_class,
+                            struct declaration_scope *parent_scope);
+static
+void _struct_type_free(struct type *type);
+
 void struct_copy(struct stream_pos *dest, const struct format *fdest, 
                 struct stream_pos *src, const struct format *fsrc,
-                const struct type_class *type_class)
+                struct type *type)
 {
-       struct type_class_struct *struct_class =
-               container_of(type_class, struct type_class_struct, p);
-       unsigned int i;
+       struct type_struct *_struct = container_of(type, struct type_struct, p);
+       struct type_class_struct *struct_class = _struct->_class;
+       unsigned long i;
 
        fsrc->struct_begin(src, struct_class);
        fdest->struct_begin(dest, struct_class);
 
-       for (i = 0; i < struct_class->fields->len; i++) {
-               struct field *field = &g_array_index(struct_class->fields,
+       for (i = 0; i < _struct->fields->len; i++) {
+               struct field *field = &g_array_index(_struct->fields,
                                                     struct field, i);
-               struct type_class *field_class = field->type_class;
+               struct type_class *field_class = field->type->p._class;
 
-               field_class->copy(dest, fdest, src, fsrc, field_class);
+               field_class->copy(dest, fdest, src, fsrc, &field->type->p);
 
        }
        fsrc->struct_end(src, struct_class);
        fdest->struct_end(dest, struct_class);
 }
 
-void struct_type_free(struct type_class_struct *struct_class)
+static
+void _struct_type_class_free(struct type_class *type_class)
 {
-       unsigned int i;
+       struct type_class_struct *struct_class =
+               container_of(type_class, struct type_class_struct, p);
+       unsigned long i;
 
        g_hash_table_destroy(struct_class->fields_by_name);
 
        for (i = 0; i < struct_class->fields->len; i++) {
-               struct field *field = &g_array_index(struct_class->fields,
-                                                    struct field, i);
-               type_unref(field->type_class);
+               struct field *type_class_field =
+                       &g_array_index(struct_class->fields,
+                                      struct type_class_field, i);
+               type_class_unref(field->type_class);
        }
        g_array_free(struct_class->fields, true);
        g_free(struct_class);
 }
 
-static void _struct_type_free(struct type_class *type_class)
-{
-       struct type_class_struct *struct_class =
-               container_of(type_class, struct type_class_struct, p);
-       struct_type_free(struct_class);
-}
-
-struct type_class_struct *struct_type_new(const char *name)
+struct type_class_struct *
+struct_type_class_new(const char *name)
 {
        struct type_class_struct *struct_class;
        struct type_class *type_class;
@@ -76,16 +80,17 @@ struct type_class_struct *struct_type_new(const char *name)
 
        struct_class = g_new(struct type_class_struct, 1);
        type_class = &struct_class->p;
-
        struct_class->fields_by_name = g_hash_table_new(g_direct_hash,
                                                        g_direct_equal);
-       struct_class->fields = g_array_sized_new(false, false,
-                                                sizeof(struct field),
+       struct_class->fields = g_array_sized_new(FALSE, TRUE,
+                                                sizeof(struct type_class_field),
                                                 DEFAULT_NR_STRUCT_FIELDS);
        type_class->name = g_quark_from_string(name);
        type_class->alignment = 1;
        type_class->copy = struct_copy;
-       type_class->free = _struct_type_free;
+       type_class->class_free = _struct_type_class_free;
+       type_class->type_new = _struct_type_new;
+       type_class->type_free = _struct_type_free;
        type_class->ref = 1;
 
        if (type_class->name) {
@@ -96,20 +101,57 @@ struct type_class_struct *struct_type_new(const char *name)
        return struct_class;
 
 error_register:
+       g_hash_table_destroy(struct_class->fields_by_name);
+       g_array_free(struct_class->fields, true);
        g_free(struct_class);
        return NULL;
 }
 
-void struct_type_add_field(struct type_class_struct *struct_class,
-                          const char *field_name,
-                          struct type_class *type_class)
+static
+struct type_struct *_struct_type_new(struct type_class *type_class,
+                                    struct declaration_scope *parent_scope)
 {
-       struct field *field;
+       struct type_class_struct *_struct_class =
+               container_of(type_class, struct type_class_struct, p);
+       struct type_struct *_struct;
+
+       _struct = g_new(struct type_struct, 1);
+       type_class_ref(&_struct_class->p);
+       _struct->p._class = _struct_class;
+       _struct->p.ref = 1;
+       _struct->scope = new_declaration_scope(parent_scope);
+       _struct->fields = g_array_sized_new(FALSE, TRUE,
+                                           sizeof(struct field),
+                                           DEFAULT_NR_STRUCT_FIELDS);
+       return &_struct->p;
+}
+
+static
+void _struct_type_free(struct type *type)
+{
+       struct type_struct *_struct = container_of(type, struct type_struct, p);
+       unsigned long i;
+
+       for (i = 0; i < _struct->fields->len; i++) {
+               struct field *field = &g_array_index(_struct->fields,
+                                                    struct field, i);
+               type_unref(field->type);
+       }
+       free_declaration_scope(_struct->scope);
+       type_class_unref(_struct->p._class);
+       g_free(_struct);
+}
+
+void struct_type_class_add_field(struct type_class_struct *struct_class,
+                                const char *field_name,
+                                struct type_class *type_class)
+{
+       struct type_class_field *field;
        unsigned long index;
 
        g_array_set_size(struct_class->fields, struct_class->fields->len + 1);
        index = struct_class->fields->len - 1;  /* last field (new) */
-       field = &g_array_index(struct_class->fields, struct field, index);
+       field = &g_array_index(struct_class->fields, struct type_class_field, index);
        field->name = g_quark_from_string(field_name);
        type_ref(type_class);
        field->type_class = type_class;
@@ -126,8 +168,8 @@ void struct_type_add_field(struct type_class_struct *struct_class,
 }
 
 unsigned long
-struct_type_lookup_field_index(struct type_class_struct *struct_class,
-                              GQuark field_name)
+struct_type_class_lookup_field_index(struct type_class_struct *struct_class,
+                                    GQuark field_name)
 {
        unsigned long index;
 
@@ -136,12 +178,22 @@ struct_type_lookup_field_index(struct type_class_struct *struct_class,
        return index;
 }
 
+/*
+ * field returned only valid as long as the field structure is not appended to.
+ */
+struct type_class_field *
+struct_type_class_get_field_from_index(struct type_class_struct *struct_class,
+                                      unsigned long index)
+{
+       return &g_array_index(struct_class->fields, struct type_class_field, index);
+}
+
 /*
  * field returned only valid as long as the field structure is not appended to.
  */
 struct field *
-struct_type_get_field_from_index(struct type_class_struct *struct_class,
+struct_type_get_field_from_index(struct type_struct *struct_type,
                                 unsigned long index)
 {
-       return &g_array_index(struct_class->fields, struct field, index);
+       return &g_array_index(struct_type->fields, struct field, index);
 }
index 6fb3e5989269e11b029f7494d0d53a2d08e7ff76..961337800a1e45472a2abd175de21448726884d5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Types registry.
  *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #include <glib.h>
 #include <errno.h>
 
-/*
- * Type hash table contains the registered types. Type registration is typically
- * performed by a type plugin.
- * TODO: support plugin unload (unregistration of types).
- */
-GHashTable *type_classes;
-
-struct type_class *lookup_type(GQuark qname)
+static
+struct type_class *lookup_type_class_scope(GQuark qname,
+                                          struct declaration_scope *scope)
 {
-       return g_hash_table_lookup(type_classes,
+       return g_hash_table_lookup(scope->type_classes,
                                   (gconstpointer) (unsigned long) qname);
 }
 
-static void free_type(struct type_class *type_class)
+struct type_class *lookup_type_class(GQuark qname,
+                                    struct declaration_scope *scope)
+{
+       struct type_class *tc;
+
+       while (scope) {
+               tc = lookup_type_class_scope(qname, scope);
+               if (tc)
+                       return tc;
+               scope = scope->parent_scope;
+       }
+       return NULL;
+}
+
+static void free_type_class(struct type_class *type_class)
+{
+       type_class->class_free(type_class);
+}
+
+static void free_type(struct type *type)
 {
-       type_class->free(type_class);
+       type->p.type_free(type);
 }
 
-int register_type(struct type_class *type_class)
+int register_type_class(struct type_class *type_class,
+                       struct declaration_scope *scope)
 {
-       if (lookup_type(type_class->name))
+       /* Only lookup in local scope */
+       if (lookup_type_class_scope(type_class->name, scope))
                return -EEXIST;
 
-       g_hash_table_insert(type_classes,
+       g_hash_table_insert(scope->type_classes,
                            (gpointer) (unsigned long) type_class->name,
                            type_class);
        return 0;
 }
 
-void type_ref(struct type_class *type_class)
+void type_class_ref(struct type_class *type_class)
 {
        type_class->ref++;
 }
 
-void type_unref(struct type_class *type_class)
+void type_class_unref(struct type_class *type_class)
 {
        if (!--type_class->ref)
-               free_type(type_class);
+               free_type_class(type_class);
 }
 
-int init_types(void)
+void type_ref(struct type *type)
 {
-       type_classes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-                                            NULL, (GDestroyNotify) free_type);
-       if (!type_classes)
-               return -ENOMEM;
-       return 0;
+       type->ref++;
 }
 
-int finalize_types(void)
+void type_unref(struct type *type)
 {
-       g_hash_table_destroy(type_classes);
-       return 0;
+       if (!--type->ref)
+               free_type(type);
+}
+
+struct declaration_scope *
+new_declaration_scope(struct declaration_scope *parent_scope)
+{
+       struct declaration_scope *scope = g_new(struct declaration_scope, 1);
+
+       scope->type_classes = g_hash_table_new_full(g_direct_hash,
+                                       g_direct_equal, NULL,
+                                       (GDestroyNotify) type_class_unref);
+       scope->parent_scope = parent_scope;
+       return scope;
+}
+
+void free_declaration_scope(struct declaration_scope *scope)
+{
+       g_hash_table_destroy(scope->type_classes);
+       g_free(scope);
 }
diff --git a/types/variant.c b/types/variant.c
new file mode 100644 (file)
index 0000000..0cf0ca6
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * variant.c
+ *
+ * BabelTrace - Variant Type Converter
+ *
+ * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <babeltrace/compiler.h>
+#include <babeltrace/format.h>
+
+
+static
+struct type *variant_type_new(struct type_class *type_class,
+                             struct declaration_scope *parent_scope);
+static
+void variant_type_free(struct type *type);
+
+void variant_copy(struct stream_pos *dest, const struct format *fdest, 
+                 struct stream_pos *src, const struct format *fsrc,
+                 struct type *type)
+{
+       struct type_variant *variant = container_of(type, struct type_variant,
+                                                   p);
+       struct type_class_variant *variant_class = variant->_class;
+       struct field *field;
+       struct type_class *field_class;
+       unsigned long i;
+
+       fsrc->variant_begin(src, variant_class);
+       fdest->variant_begin(dest, variant_class);
+
+       field = variant_type_get_current_field(variant);
+       field_class = field->type->p._class;
+       field_class->copy(dest, fdest, src, fsrc, &field->type->p);
+
+       fsrc->variant_end(src, variant_class);
+       fdest->variant_end(dest, variant_class);
+}
+
+static
+void variant_type_class_free(struct type_class *type_class)
+{
+       struct type_class_variant *variant_class =
+               container_of(type_class, struct type_class_variant, p);
+       unsigned long i;
+
+       g_hash_table_destroy(struct_class->fields_by_tag);
+
+       for (i = 0; i < variant_class->fields->len; i++) {
+               struct field *type_class_field =
+                       &g_array_index(variant_class->fields,
+                                      struct type_class_field, i);
+               type_class_unref(field->type_class);
+       }
+       g_array_free(variant_class->fields, true);
+       g_free(variant_class);
+}
+
+struct type_class_variant *
+variant_type_class_new(const char *name)
+{
+       struct type_class_variant *variant_class;
+       struct type_class *type_class;
+       int ret;
+
+       variant_class = g_new(struct type_class_variant, 1);
+       type_class = &variant_class->p;
+       variant_class->fields_by_tag = g_hash_table_new(g_direct_hash,
+                                                       g_direct_equal);
+       variant_class->fields = g_array_sized_new(FALSE, TRUE,
+                                                 sizeof(struct type_class_field),
+                                                 DEFAULT_NR_STRUCT_FIELDS);
+       type_class->name = g_quark_from_string(name);
+       type_class->alignment = 1;
+       type_class->copy = variant_copy;
+       type_class->class_free = _variant_type_class_free;
+       type_class->type_new = _variant_type_new;
+       type_class->type_free = _variant_type_free;
+       type_class->ref = 1;
+
+       if (type_class->name) {
+               ret = register_type(type_class);
+               if (ret)
+                       goto error_register;
+       }
+       return struct_class;
+
+error_register:
+       g_hash_table_destroy(variant_class->fields_by_tag);
+       g_array_free(variant_class->fields, true);
+       g_free(variant_class);
+       return NULL;
+}
+
+static
+struct type_variant *_variant_type_new(struct type_class *type_class,
+                                      struct declaration_scope *parent_scope)
+{
+       struct type_class_variant *variant_class =
+               container_of(type_class, struct type_class_variant, p);
+       struct type_struct *variant;
+
+       variant = g_new(struct type_variant, 1);
+       type_class_ref(&variant_class->p);
+       variant->p._class = variant_class;
+       variant->p.ref = 1;
+       variant->scope = new_declaration_scope(parent_scope);
+       variant->fields = g_array_sized_new(FALSE, TRUE,
+                                           sizeof(struct field),
+                                           DEFAULT_NR_STRUCT_FIELDS);
+       variant->current_field = NULL;
+       return &variant->p;
+}
+
+static
+void variant_type_free(struct type *type)
+{
+       struct type_variant *variant = container_of(type, struct type_variant,
+                                                   p);
+       unsigned long i;
+
+       for (i = 0; i < variant->fields->len; i++) {
+               struct field *field = &g_array_index(variant->fields,
+                                                    struct field, i);
+               type_unref(field->type);
+       }
+       free_declaration_scope(variant->scope);
+       type_class_unref(variant->p._class);
+       g_free(variant);
+}
+
+void variant_type_class_add_field(struct type_class_variant *variant_class,
+                                 const char *tag_name,
+                                 struct type_class *type_class)
+{
+       struct type_class_field *field;
+       unsigned long index;
+
+       g_array_set_size(variant_class->fields, variant_class->fields->len + 1);
+       index = variant_class->fields->len - 1; /* last field (new) */
+       field = &g_array_index(variant_class->fields, struct type_class_field, index);
+       field->name = g_quark_from_string(tag_name);
+       type_ref(type_class);
+       field->type_class = type_class;
+       /* Keep index in hash rather than pointer, because array can relocate */
+       g_hash_table_insert(variant_class->fields_by_name,
+                           (gpointer) (unsigned long) field->name,
+                           (gpointer) index);
+       /*
+        * Alignment of variant is based on the alignment of its currently
+        * selected choice, so we leave variant alignment as-is (statically
+        * speaking).
+        */
+}
+
+struct type_class_field *
+struct_type_class_get_field_from_tag(struct type_class_variant *variant_class,
+                                    GQuark tag)
+{
+       unsigned long index;
+
+       index = (unsigned long) g_hash_table_lookup(variant_class->fields_by_tag,
+                                                   (gconstpointer) (unsigned long) tag);
+       return &g_array_index(variant_class->fields, struct type_class_field, index);
+}
+
+/*
+ * tag_instance is assumed to be an enumeration.
+ */
+int variant_type_set_tag(struct type_variant *variant,
+                        struct type *enum_tag_instance)
+{
+       struct type_enum *_enum =
+               container_of(struct type_enum, variant->enum_tag, p);
+       struct type_class_enum *enum_class = _enum->_class;
+       int missing_field = 0;
+       unsigned long i;
+
+       /*
+        * Strictly speaking, each enumerator must map to a field of the
+        * variant. However, we are even stricter here by requiring that each
+        * variant choice map to an enumerator too. We then validate that the
+        * number of enumerators equals the number of variant choices.
+        */
+       if (variant->_class->fields->len != enum_get_nr_enumerators(enum_class))
+               return -EPERM;
+
+       for (i = 0; i < variant->_class->fields->len; i++) {
+               struct type_class_field *field_class =
+                       &g_array_index(variant->_class->fields,
+                                      struct type_class_field, i);
+               if (!enum_quark_to_range_set(enum_class, field_class->name)) {
+                       missing_field = 1;
+                       break;
+               }
+       }
+       if (missing_field)
+               return -EPERM;
+
+       /*
+        * Check the enumeration: it must map each value to one and only one
+        * enumerator tag.
+        * TODO: we should also check that each range map to one and only one
+        * tag. For the moment, we will simply check this dynamically in
+        * variant_type_get_current_field().
+        */
+
+       /* Set the enum tag field */
+       variant->enum_tag = enum_tag_instance;
+       return 0;
+}
+
+/*
+ * field returned only valid as long as the field structure is not appended to.
+ */
+struct field *
+variant_type_get_current_field(struct type_variant *variant)
+{
+       struct type_enum *_enum =
+               container_of(struct type_enum, variant->enum_tag, p);
+       struct variat_type_class *variant_class = variant->_class;
+       unsigned long index;
+       GArray *tag_array;
+       GQuark tag;
+
+       tag_array = _enum->value;
+       /*
+        * The 1 to 1 mapping from enumeration to value should have been already
+        * checked. (see TODO above)
+        */
+       assert(tag_array->len == 1);
+       tag = g_array_index(tag_array, GQuark, 0);
+       index = (unsigned long) g_hash_table_lookup(variant_class->fields_by_tag,
+                                                   (gconstpointer) (unsigned long) tag);
+       return &g_array_index(variant_class->fields, struct field, index);
+}
This page took 0.079935 seconds and 4 git commands to generate.