From 448d3cc7640830015850cc6287532d4c194fe690 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 30 Sep 2010 15:57:54 -0400 Subject: [PATCH] Manage enumerations at the library level .. rather than keeping a table individually for each format. Signed-off-by: Mathieu Desnoyers --- formats/ctf/ctf.c | 6 +- formats/ctf/types/enum.c | 195 +++++++--------------------- include/babeltrace/ctf/types.h | 16 +-- include/babeltrace/format.h | 51 +++++--- include/babeltrace/types.h | 31 ++++- types/bitfield.c | 7 +- types/enum.c | 225 +++++++++++++++++++++++++++++++++ types/float.c | 7 +- types/integer.c | 7 +- 9 files changed, 344 insertions(+), 201 deletions(-) create mode 100644 types/enum.c diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 0f0d6921..017d0e05 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -38,10 +38,8 @@ static const struct format ctf_format = { .double_write = ctf_double_write, .float_copy = ctf_float_copy, .string_copy = ctf_string_copy, - .enum_uint_to_quark = ctf_enum_uint_to_quark, - .enum_int_to_quark = ctf_enum_int_to_quark, - .enum_quark_to_uint = ctf_enum_quark_to_uint, - .enum_quark_to_int = ctf_enum_quark_to_int, + .enum_read = ctf_enum_read, + .enum_write = ctf_enum_write, }; void ctf_init(void) diff --git a/formats/ctf/types/enum.c b/formats/ctf/types/enum.c index 5e0fda7d..256807a7 100644 --- a/formats/ctf/types/enum.c +++ b/formats/ctf/types/enum.c @@ -24,151 +24,52 @@ #include #include -struct enum_table { - GHashTable *value_to_quark; /* Tuples (value, GQuark) */ - GHashTable *quark_to_value; /* Tuples (GQuark, value) */ -}; - -#if (__WORDSIZE == 32) -GQuark enum_uint_to_quark(const struct enum_table *table, uint64_t v) -{ - gconstpointer q = g_hash_table_lookup(table->value_to_quark, &v); - return (GQuark) (unsigned long) q; -} - -GQuark enum_int_to_quark(const struct enum_table *table, uint64_t v) -{ - gconstpointer q = g_hash_table_lookup(table->value_to_quark, &v); - return (GQuark) (unsigned long) q; -} - -uint64_t enum_quark_to_uint(size_t len, int byte_order, GQuark q) -{ - gconstpointer v = g_hash_table_lookup(table->quark_to_value, - (gconstpointer) q); - return *(const uint64_t *) v; -} - -int64_t enum_quark_to_int(size_t len, int byte_order, GQuark q) -{ - gconstpointer v = g_hash_table_lookup(table->quark_to_value, - (gconstpointer) q); - return *(const int64_t *) v; -} - -guint enum_val_hash(gconstpointer key) -{ - int64_t ukey = *(const int64_t *)key; - - return (guint)ukey ^ (guint)(ukey >> 32); -} - -gboolean enum_val_equal(gconstpointer a, gconstpointer b) -{ - int64_t ua = *(const int64_t *)a; - int64_t ub = *(const int64_t *)b; - - return ua == ub; -} - -void enum_val_free(void *ptr) -{ - g_free(ptr); -} - -void enum_signed_insert(struct enum_table *table, int64_t v, GQuark q) -{ - int64_t *valuep = g_new(int64_t, 1); - - g_hash_table_insert(table->value_to_quark, valuep, - (gpointer) (unsigned long) q); - g_hash_table_insert(table->quark_to_value, (gpointer) (unsigned long) q, - valuep); -} - -void enum_unsigned_insert(struct enum_table *table, uint64_t v, GQuark q) -{ - uint64_t *valuep = g_new(uint64_t, 1); - - g_hash_table_insert(table->value_to_quark, valuep, - (gpointer) (unsigned long) q); - g_hash_table_insert(table->quark_to_value, (gpointer) (unsigned long) q, - valuep); -} -#else /* __WORDSIZE != 32 */ -GQuark enum_uint_to_quark(const struct enum_table *table, uint64_t v) -{ - gconstpointer q = g_hash_table_lookup(table->value_to_quark, - (gconstpointer) v); - return (GQuark) (unsigned long) q; -} - -GQuark enum_int_to_quark(const struct enum_table *table, uint64_t v) -{ - gconstpointer q = g_hash_table_lookup(table->value_to_quark, - (gconstpointer) v); - return (GQuark) (unsigned long) q; -} - -uint64_t enum_quark_to_uint(size_t len, int byte_order, GQuark q) -{ - gconstpointer v = g_hash_table_lookup(table->quark_to_value, - (gconstpointer) (unsigned long) q); - return *(const uint64_t *) v; -} - -int64_t enum_quark_to_int(size_t len, int byte_order, GQuark q) -{ - gconstpointer v = g_hash_table_lookup(table->quark_to_value, - (gconstpointer) (unsigned long) q); - return *(const int64_t *) v; -} - -guint enum_val_hash(gconstpointer key) -{ - return g_direct_hash(key); -} - -gboolean enum_val_equal(gconstpointer a, gconstpointer b) -{ - return g_direct_equal(a, b); -} - -void enum_val_free(void *ptr) -{ -} - -void enum_signed_insert(struct enum_table *table, int64_t v, GQuark q) -{ - g_hash_table_insert(table->value_to_quark, (gpointer) v, - (gpointer) (unsigned long) q); - g_hash_table_insert(table->quark_to_value, (gpointer) (unsigned long) q, - valuep); -} - -void enum_unsigned_insert(struct enum_table *table, uint64_t v, GQuark q) -{ - g_hash_table_insert(table->value_to_quark, (gpointer) v, - (gpointer) (unsigned long) q); - g_hash_table_insert(table->quark_to_value, (gpointer) (unsigned long) q, - valuep); -} -#endif /* __WORDSIZE != 32 */ - -struct enum_table *enum_new(void) -{ - struct enum_table *table; - - table = g_new(struct enum_table, 1); - table->value_to_quark = g_hash_table(enum_val_hash, enum_val_equal); - table->quark_to_value = g_hash_table_new_full(g_direct_hash, - g_direct_equal, - NULL, enum_val_free); -} - -void enum_destroy(struct enum_table *table) -{ - g_hash_table_destroy(table->value_to_quark); - g_hash_table_destroy(table->quark_to_value); - g_free(table); +GQuark ctf_enum_read(const unsigned char *ptr, + const struct type_class_enum *src) +{ + struct type_class_bitfield *bitfield_class = &src->p; + struct type_class_integer *int_class = &bitfield_class->p; + + if (!int_class->signedness) { + uint64_t v; + + v = ctf_bitfield_unsigned_read(src, + bitfield_class->start_offset, + int_class->len, + int_class->byte_order); + return enum_uint_to_quark(src, v); + } else { + int64_t v; + + v = fsrc->bitfield_signed_read(src, + bitfield_class->start_offset, + int_class->len, + int_class->byte_order); + return enum_int_to_quark(src, v); + } +} + +size_t ctf_enum_write(unsigned char *ptr, const struct type_class_enum *dest, + GQuark q) +{ + struct type_class_bitfield *bitfield_class = &dest->p; + struct type_class_integer *int_class = &bitfield_class->p; + + if (!int_class->signedness) { + uint64_t v; + + v = enum_quark_to_uint(dest, q); + return ctf_bitfield_unsigned_write(src, + bitfield_class->start_offset, + int_class->len, + int_class->byte_order, v); + } else { + int64_t v; + + v = enum_quark_to_int(dest, q); + return ctf_bitfield_signed_write(src, + bitfield_class->start_offset, + int_class->len, + int_class->byte_order, v); + } } diff --git a/include/babeltrace/ctf/types.h b/include/babeltrace/ctf/types.h index 2d06d6a5..0f0615f4 100644 --- a/include/babeltrace/ctf/types.h +++ b/include/babeltrace/ctf/types.h @@ -65,17 +65,9 @@ void ctf_float_copy(unsigned char *destp, const struct type_class_float *dest, size_t ctf_string_copy(unsigned char *dest, const unsigned char *src); -/* - * A GQuark can be translated to/from strings with g_quark_from_string() and - * g_quark_to_string(). - */ -GQuark ctf_enum_uint_to_quark(const struct enum_table *table, uint64_t v); -GQuark ctf_enum_int_to_quark(const struct enum_table *table, uint64_t v); -uint64_t ctf_enum_quark_to_uint(size_t len, int byte_order, GQuark q); -int64_t ctf_enum_quark_to_int(size_t len, int byte_order, GQuark q); -void ctf_enum_signed_insert(struct enum_table *table, int64_t v, GQuark q); -void ctf_enum_unsigned_insert(struct enum_table *table, uint64_t v, GQuark q); -struct enum_table *ctf_enum_new(void); -void ctf_enum_destroy(struct enum_table *table); +GQuark ctf_enum_read(const unsigned char *ptr, + const struct type_class_enum *src); +size_t ctf_enum_write(unsigned char *ptr, const struct type_class_enum *dest, + GQuark q); #endif /* _BABELTRACE_CTF_TYPES_H */ diff --git a/include/babeltrace/format.h b/include/babeltrace/format.h index d31ee831..ac03dba7 100644 --- a/include/babeltrace/format.h +++ b/include/babeltrace/format.h @@ -31,36 +31,45 @@ struct format { uint64_t (*uint_read)(const uint8_t *ptr, size_t len, int byte_order); int64_t (*int_read)(const uint8_t *ptr, size_t len, int byte_order); - size_t (*uint_write)(uint8_t *ptr, size_t len, int byte_order, uint64_t v); - size_t (*int_write)(uint8_t *ptr, size_t len, int byte_order, int64_t v); + size_t (*uint_write)(uint8_t *ptr, size_t len, int byte_order, + uint64_t v); + size_t (*int_write)(uint8_t *ptr, size_t len, int byte_order, + int64_t v); uint64_t (*bitfield_unsigned_read)(const unsigned char *ptr, - unsigned long start, unsigned long len, - int byte_order); + unsigned long start, + unsigned long len, + int byte_order); int64_t (*bitfield_signed_read)(const unsigned char *ptr, - unsigned long start, unsigned long len, - int byte_order); + unsigned long start, unsigned long len, + int byte_order); size_t (*bitfield_unsigned_write)(unsigned char *ptr, - unsigned long start, unsigned long len, - int byte_order, uint64_t v); + unsigned long start, + unsigned long len, + int byte_order, uint64_t v); size_t (*bitfield_signed_write)(unsigned char *ptr, - unsigned long start, unsigned long len, - int byte_order, int64_t v); - - - void (*float_copy)(unsigned char *destp, const struct type_class_float *dest, - const unsigned char *srcp, const struct type_class_float *src); - double (*double_read)(const unsigned char *ptr, const struct type_class_float *src); - size_t (*double_write)(unsigned char *ptr, const struct type_class_float *dest, - double v); + unsigned long start, + unsigned long len, + int byte_order, int64_t v); + void (*float_copy)(unsigned char *destp, + const struct type_class_float *dest, + const unsigned char *srcp, + const struct type_class_float *src); + double (*double_read)(const unsigned char *ptr, + const struct type_class_float *src); + size_t (*double_write)(unsigned char *ptr, + const struct type_class_float *dest, + double v); size_t (*string_copy)(unsigned char *dest, const unsigned char *src); - GQuark (*enum_uint_to_quark)(const struct enum_table *table, uint64_t v); - GQuark (*enum_int_to_quark)(const struct enum_table *table, uint64_t v); - uint64_t (*enum_quark_to_uint)(size_t len, int byte_order, GQuark q); - int64_t (*enum_quark_to_int)(size_t len, int byte_order, GQuark q); + GQuark (*enum_read)(const unsigned char *ptr, + const struct type_class_enum *src); + size_t (*enum_write)(unsigned char *ptr, + const struct type_class_enum *dest, + GQuark q); + }; struct format *bt_lookup_format(GQuark qname); diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index b77ac400..3dea99e5 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -57,9 +57,14 @@ struct type_class_float { /* TODO: we might want to express more info about NaN, +inf and -inf */ }; +struct enum_table { + GHashTable *value_to_quark; /* Tuples (value, GQuark) */ + GHashTable *quark_to_value; /* Tuples (GQuark, value) */ +}; + struct type_class_enum { - struct type_class_bitfield; /* inherit from bitfield */ - struct enum_table *table; + struct type_class_bitfield p; /* inherit from bitfield */ + struct enum_table table; }; struct type_class_struct { @@ -90,4 +95,26 @@ struct type_class_float *float_type_new(const char *name, 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 + * g_quark_to_string(). + */ +GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v); +GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v); +uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q); +int64_t enum_quark_to_int(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q); +void enum_signed_insert(struct type_class_enum *enum_class, + int64_t v, GQuark q); +void enum_unsigned_insert(struct type_class_enum *enum_class, + uint64_t v, GQuark q); + +struct type_class_enum *enum_type_new(const char *name, + size_t start_offset, + size_t len, int byte_order, + int signedness, + size_t alignment); +void enum_type_free(struct type_class_enum *enum_class); + #endif /* _BABELTRACE_TYPES_H */ diff --git a/types/bitfield.c b/types/bitfield.c index b21fdc91..03d3bbcb 100644 --- a/types/bitfield.c +++ b/types/bitfield.c @@ -19,6 +19,7 @@ */ #include +#include #include /* @@ -83,9 +84,6 @@ struct type_class_bitfield *bitfield_type_new(const char *name, struct type_class_integer *int_class; int ret; - /* - * Freed when type is unregistered. - */ bitfield_class = g_new(struct type_class_bitfield, 1); int_class = &bitfield_class->p; int_class->p.name = g_quark_from_string(name); @@ -106,6 +104,5 @@ struct type_class_bitfield *bitfield_type_new(const char *name, void bitfield_type_free(struct type_class_bitfield *bitfield_class) { - if (!bitfield_class->name) - g_free(bitfield_class); + g_free(bitfield_class); } diff --git a/types/enum.c b/types/enum.c new file mode 100644 index 00000000..21af948b --- /dev/null +++ b/types/enum.c @@ -0,0 +1,225 @@ +/* + * BabelTrace - Enumeration Type + * + * 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 +#include +#include + +struct enum_table { + GHashTable *value_to_quark; /* Tuples (value, GQuark) */ + GHashTable *quark_to_value; /* Tuples (GQuark, value) */ +}; + +#if (__WORDSIZE == 32) +GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) +{ + gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, + &v); + return (GQuark) (unsigned long) q; +} + +GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) +{ + gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, + &v); + return (GQuark) (unsigned long) q; +} + +uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q) +{ + gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, + (gconstpointer) q); + return *(const uint64_t *) v; +} + +int64_t enum_quark_to_int(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q) +{ + gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, + (gconstpointer) q); + return *(const int64_t *) v; +} + +guint enum_val_hash(gconstpointer key) +{ + int64_t ukey = *(const int64_t *)key; + + return (guint)ukey ^ (guint)(ukey >> 32); +} + +gboolean enum_val_equal(gconstpointer a, gconstpointer b) +{ + int64_t ua = *(const int64_t *)a; + int64_t ub = *(const int64_t *)b; + + return ua == ub; +} + +void enum_val_free(void *ptr) +{ + g_free(ptr); +} + +void enum_signed_insert(struct type_class_enum *enum_class, int64_t v, GQuark q) +{ + int64_t *valuep = g_new(int64_t, 1); + + g_hash_table_insert(enum_class->table>value_to_quark, valuep, + (gpointer) (unsigned long) q); + g_hash_table_insert(enum_class->table.quark_to_value, + (gpointer) (unsigned long) q, + valuep); +} + +void enum_unsigned_insert(struct type_class_enum *enum_class, uint64_t v, GQuark q) +{ + uint64_t *valuep = g_new(uint64_t, 1); + + g_hash_table_insert(enum_class->table.value_to_quark, valuep, + (gpointer) (unsigned long) q); + g_hash_table_insert(enum_class->table.quark_to_value, + (gpointer) (unsigned long) q, + valuep); +} +#else /* __WORDSIZE != 32 */ +GQuark enum_uint_to_quark(const struct type_class_enum *enum_class, uint64_t v) +{ + gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, + (gconstpointer) v); + return (GQuark) (unsigned long) q; +} + +GQuark enum_int_to_quark(const struct type_class_enum *enum_class, uint64_t v) +{ + gconstpointer q = g_hash_table_lookup(enum_class->table.value_to_quark, + (gconstpointer) v); + return (GQuark) (unsigned long) q; +} + +uint64_t enum_quark_to_uint(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q) +{ + gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, + (gconstpointer) (unsigned long) q); + return *(const uint64_t *) v; +} + +int64_t enum_quark_to_int(const struct type_class_enum *enum_class, + size_t len, int byte_order, GQuark q) +{ + gconstpointer v = g_hash_table_lookup(enum_class->table.quark_to_value, + (gconstpointer) (unsigned long) q); + return *(const int64_t *) v; +} + +guint enum_val_hash(gconstpointer key) +{ + return g_direct_hash(key); +} + +gboolean enum_val_equal(gconstpointer a, gconstpointer b) +{ + return g_direct_equal(a, b); +} + +void enum_val_free(void *ptr) +{ +} + +void enum_signed_insert(struct type_class_enum *enum_class, + int64_t v, GQuark q) +{ + g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, + (gpointer) (unsigned long) q); + g_hash_table_insert(enum_class->table.quark_to_value, + (gpointer) (unsigned long) q, + valuep); +} + +void enum_unsigned_insert(struct type_class_enum *enum_class, + uint64_t v, GQuark q) +{ + g_hash_table_insert(enum_class->table.value_to_quark, (gpointer) v, + (gpointer) (unsigned long) q); + g_hash_table_insert(enum_class->table.quark_to_value, + (gpointer) (unsigned long) q, + valuep); +} +#endif /* __WORDSIZE != 32 */ + +size_t enum_copy(unsigned char *dest, const struct format *fdest, + const unsigned char *src, const struct format *fsrc, + const struct type_class *type_class) +{ + struct type_class_enum *enum_class = + container_of(type_class, struct type_class_enum, p); + struct type_class_bitfield *bitfield_class = &enum_class->p; + struct type_class_integer *int_class = &bitfield_class->p; + GQuark v; + + v = fsrc->enum_read(src, enum_class) + return fdest->enum_write(dest, enum_class, v); +} + +struct type_class_enum *enum_type_new(const char *name, + size_t start_offset, + size_t len, int byte_order, + int signedness, + size_t alignment) +{ + struct type_class_bitfield *bitfield_class; + struct type_class_integer *int_class; + int ret; + + enum_class = g_new(struct type_class_bitfield, 1); + enum_class->table.value_to_quark = g_hash_table(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); + bitfield_class = &enum_class->p; + bitfield_class->start_offset = start_offset; + int_class = &bitfield_class->p; + int_class->p.name = g_quark_from_string(name); + int_class->p.alignment = alignment; + int_class->len = len; + int_class->byte_order = byte_order; + int_class->signedness = signedness; + bitfield_class->start_offset = start_offset; + if (int_class->p.name) { + ret = register_type(&int_class->p); + if (ret) { + g_hash_table_destroy(enum_class->table.value_to_quark); + g_hash_table_destroy(enum_class->table.quark_to_value); + g_free(enum_class); + return NULL; + } + } + return enum_class; +} + +void enum_type_free(struct type_class_enum *enum_class) +{ + g_hash_table_destroy(enum_class->table.value_to_quark); + g_hash_table_destroy(enum_class->table.quark_to_value); + g_free(enum_class); +} diff --git a/types/float.c b/types/float.c index ac152559..78499c8f 100644 --- a/types/float.c +++ b/types/float.c @@ -19,6 +19,7 @@ */ #include +#include size_t float_copy(unsigned char *dest, const struct format *fdest, const unsigned char *src, const struct format *fsrc, @@ -46,9 +47,6 @@ struct type_class_float *float_type_new(const char *name, struct type_class_float *float_class; int ret; - /* - * Freed when type is unregistered. - */ float_class = g_new(struct type_class_float, 1); float_class->p.name = g_quark_from_string(name); float_class->p.alignment = alignment; @@ -67,6 +65,5 @@ struct type_class_float *float_type_new(const char *name, void float_type_free(struct type_class_float *float_class) { - if (!float_class->name) - g_free(float_class); + g_free(float_class); } diff --git a/types/integer.c b/types/integer.c index b338a591..cf01f07a 100644 --- a/types/integer.c +++ b/types/integer.c @@ -20,6 +20,7 @@ #include #include +#include #include size_t integer_copy(unsigned char *dest, const struct format *fdest, @@ -56,9 +57,6 @@ struct type_class_integer *integer_type_new(const char *name, struct type_class_integer *int_class; int ret; - /* - * Freed when type is unregistered. - */ int_class = g_new(struct type_class_integer, 1); int_class->p.name = g_quark_from_string(name); int_class->p.alignment = alignment; @@ -78,6 +76,5 @@ struct type_class_integer *integer_type_new(const char *name, void integer_type_free(struct type_class_integer *int_class) { - if (!int_class->name) - g_free(int_class); + g_free(int_class); } -- 2.34.1