From 11796b9629d5a870163e4edd67e457576553aaef Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 4 Oct 2010 22:50:13 -0400 Subject: [PATCH] Add structures Signed-off-by: Mathieu Desnoyers --- formats/ctf/ctf.c | 2 + formats/ctf/types/struct.c | 11 ++- include/babeltrace/ctf/types.h | 4 + include/babeltrace/format.h | 5 +- include/babeltrace/types.h | 51 ++++++++++++- types/enum.c | 4 +- types/struct.c | 134 +++++++++++++++++++++++++++++++++ 7 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 types/struct.c diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index eec36148..63fe47e3 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -39,6 +39,8 @@ static const struct format ctf_format = { .string_free_temp = ctf_string_free_temp, .enum_read = ctf_enum_read, .enum_write = ctf_enum_write, + .struct_begin = ctf_struct_begin, + .struct_end = ctf_struct_end, }; void ctf_init(void) diff --git a/formats/ctf/types/struct.c b/formats/ctf/types/struct.c index 8d248da1..729c456e 100644 --- a/formats/ctf/types/struct.c +++ b/formats/ctf/types/struct.c @@ -1,7 +1,7 @@ /* * Common Trace Format * - * Structure write/access functions. + * Structure format access functions. * * Copyright (c) 2010 Mathieu Desnoyers * @@ -23,4 +23,13 @@ #include #include +void ctf_struct_begin(struct stream_pos *pos, + const struct type_class_struct *struct_class) +{ + align_pos(pos, struct_class->p.alignment); +} +void ctf_struct_end(struct stream_pos *pos, + const struct type_class_struct *struct_class) +{ +} diff --git a/include/babeltrace/ctf/types.h b/include/babeltrace/ctf/types.h index 49427a5b..75b8bd3e 100644 --- a/include/babeltrace/ctf/types.h +++ b/include/babeltrace/ctf/types.h @@ -72,5 +72,9 @@ GQuark ctf_enum_read(struct stream_pos *pos, void ctf_enum_write(struct stream_pos *pos, const struct type_class_enum *dest, GQuark q); +void ctf_struct_begin(struct stream_pos *pos, + const struct type_class_struct *struct_class); +void ctf_struct_end(struct stream_pos *pos, + const struct type_class_struct *struct_class); #endif /* _BABELTRACE_CTF_TYPES_H */ diff --git a/include/babeltrace/format.h b/include/babeltrace/format.h index 5909ce39..bc2bdb06 100644 --- a/include/babeltrace/format.h +++ b/include/babeltrace/format.h @@ -62,7 +62,10 @@ struct format { void (*enum_write)(struct stream_pos *pos, const struct type_class_enum *dest, GQuark q); - + void (*struct_begin)(struct stream_pos *pos, + const struct type_class_struct *struct_class); + void (*struct_end)(struct stream_pos *pos, + const struct type_class_struct *struct_class); }; struct format *bt_lookup_format(GQuark qname); diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index 305d553d..ada6c6d1 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -27,6 +27,9 @@ #include #include +/* Preallocate this many fields for structures */ +#define DEFAULT_NR_STRUCT_FIELDS 8 + /* * Always update stream_pos with move_pos and init_pos. */ @@ -128,9 +131,27 @@ struct type_class_string { struct type_class p; }; +struct field { + GQuark name; + struct type_class *type_class; +}; + struct type_class_struct { struct type_class p; - /* TODO */ + GHashTable *fields_by_name; /* Tuples (field name, field index) */ + GArray *fields; /* Array of fields */ +}; + +struct type_class_array { + struct type_class p; + size_t len; + struct type_class *elem; +}; + +struct type_class_sequence { + struct type_class p; + struct type_class_integer *len; + struct type_class *elem; }; struct type_class *ctf_lookup_type(GQuark qname); @@ -175,4 +196,32 @@ struct type_class_enum *enum_type_new(const char *name, 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, + GQuark 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); +/* + * 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, + unsigned long index); + +struct type_class_array *array_type_new(const char *name, + size_t len, + struct type_class *elem_class); +void array_type_free(struct type_class_array *array_class); + +struct type_class_sequence *sequence_type_new(const char *name, + struct type_class_integer *int_class, + struct type_class *elem_class); +void array_type_free(struct type_class_array *array_class); + #endif /* _BABELTRACE_TYPES_H */ diff --git a/types/enum.c b/types/enum.c index 8e8ef694..57ecbdd1 100644 --- a/types/enum.c +++ b/types/enum.c @@ -203,8 +203,8 @@ struct type_class_enum *enum_type_new(const char *name, int ret; enum_class = g_new(struct type_class_enum, 1); - enum_class->table.value_to_quark = g_hash_table(enum_val_hash, - enum_val_equal); + enum_class->table.value_to_quark = g_hash_table_new(enum_val_hash, + enum_val_equal); enum_class->table.quark_to_value = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, enum_val_free); diff --git a/types/struct.c b/types/struct.c new file mode 100644 index 00000000..8c1a5834 --- /dev/null +++ b/types/struct.c @@ -0,0 +1,134 @@ +/* + * BabelTrace - Structure Type Converter + * + * Copyright (c) 2010 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +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_class_struct *struct_class = + container_of(type_class, struct type_class_struct, p); + unsigned int 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, + struct field, i); + struct type_class *field_class = field->type_class; + + field_class->copy(dest, fdest, src, fsrc, type_class); + + } + fsrc->struct_end(src, struct_class); + fdest->struct_end(dest, struct_class); +} + +void struct_type_free(struct type_class_struct *struct_class) +{ + g_hash_table_destroy(struct_class->fields_by_name); + 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_class; + int ret; + + struct_class = g_new(struct type_class_struct, 1); + type_class = &float_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), + 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; + + if (type_class->name) { + ret = ctf_register_type(type_class); + if (ret) + goto error_register; + } + return struct_class; + +error_register: + 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) +{ + struct 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->name = g_quark_from_string(field_name); + field->type_class = type_class; + /* Keep index in hash rather than pointer, because array can relocate */ + g_hash_table_insert(struct_class->fields_by_name, + (gpointer) (unsigned long) field->name, + (gpointer) index); + /* + * Alignment of structure is the max alignment of types contained + * therein. + */ + struct_class->p.alignment = max(struct_class->p.alignment, + type_class->alignment); +} + +unsigned long +struct_type_lookup_field_index(struct type_class_struct *struct_class, + GQuark field_name) +{ + unsigned long index; + + index = (unsigned long) g_hash_table_lookup(struct_class->fields_by_name, + field_name); + return 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, + unsigned long index) +{ + return &g_array_index(struct_class->fields, struct field, index); +} -- 2.34.1